请选择 进入手机版 | 继续访问电脑版

大话骰

 找回密码
 立即注册
搜索
查看: 101|回复: 0

C语言写一个掷骰子的游戏

[复制链接]

1万

主题

1万

帖子

3万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
38803
发表于 4 天前 | 显示全部楼层 |阅读模式


我们将要模拟一个非常流行的游戏——掷骰子。骰子的形式多种多样,最普遍的是使用两个6面骰子。在一些冒险游戏中,会使用5种骰子:4面、6面、8面、12面和20面。聪明的古希腊人证明了只有5种正多面体,它们的所有面都具有相同的形状和大小。各种不同类型的骰子就是根据这些正多面体发展而来。也可以做成其他面数的,但是其所有的面不会都相等,因此各个面朝上的几率就不同。

计算机计算不用考虑几何的限制,所以可以设计任意面数的电子骰子。我们先从6面开始。

我们想获得1~6的随机数。然而,rand()生成的随机数在0~RAND_MAX之间。RAND_MAX被定义在stdlib.h中,其值通常是INT_MAX。因此,需要进行一些调整,方法如下。

1.把随机数求模6,获得的整数在0~5之间。
2.结果加1,新值在1~6之间。
3.为方便以后扩展,把第1步中的数字6替换成骰子面数。下面的代码实现了这3个步骤:
#include <stdlib.h>   /* for rand() */int rollem(int sides){    int roll;    roll = rand() % sides + 1;    return roll;}
我们还想用一个函数提示用户选择任意面数的骰子,并返回点数总和。如以下程序diceroll.c所示。
/* diceroll.c -- dice role simulation *//* compile with mandydice.c           */ #include "diceroll.h"#include <stdio.h>#include <stdlib.h>           /* for library rand()   */int roll_count  = 0;          /* external linkage     */static int rollem(int sides)  /* private to this file */{    int roll;    roll = rand() % sides + 1;    ++roll_count;             /* count function calls */    return roll;}int roll_n_dice(int dice, int sides){    int d;    int total = 0;    if (sides < 2)    {        printf("Need at least 2 sides.n");        return -2;    }    if (dice < 1)    {        printf("Need at least 1 die.n");        return -1;    }    for (d = 0; d < dice; d++)        total += rollem(sides);    return total;}
该文件加入了新元素。

第一,rollem()函数属于该文件私有,它是roll_n_dice()的辅助函数。

第二,为了演示外部链接的特性,该文件声明了一个外部变量roll_count。该变量统计调用rollem()函数的次数。这样设计有点蹩脚,仅为了演示外部变量的特性。

第三,该文件包含以下预处理指令:
#include "diceroll.h"
如果使用标准库函数,如rand(),要在当前文件中包含标准头文件(对rand()而言要包含stdlib.h),而不是声明该函数。因为头文件中已经包含了正确的函数原型。我们效仿这一做法,把roll_n_dice()函数的原型放在diceroll.h头文件中。把文件名放在双引号中而不是尖括号中,指示编译器在本地查找文件,而不是到编译器存放标准头文件的位置去查找文件。“本地查找”的含义取决于具体的实现。一些常见的实现把头文件与源代码文件或工程文件(如果编译器使用它们的话)放在相同的目录或文件夹中。程序diceroll.h是头文件中的内容。
//diceroll.hextern int roll_count;int roll_n_dice(int dice, int sides);
该头文件中包含一个函数原型和一个extern声明。由于diceroll.c文件包含了该文件,direroll.c实际上包含了roll_count的两个声明:
extern int roll_count;  // from header fileint roll_count = 0;     // from source code file
这样做没问题。一个变量只能有一个定义式声明,但是带extern的声明是引用式声明,可以有多个引用式声明。

使用roll_n_dice()函数的程序都要包含diceroll.h头文件。包含该头文件后,程序便可使用roll_n_dice()函数和roll_count变量。如程序manydice.c所示。
/* manydice.c -- multiple dice rolls                    *//* compile with diceroll.c                              */#include <stdio.h>#include <stdlib.h>              /* for library srand() */#include <time.h>                /* for time()          */#include "diceroll.h"            /* for roll_n_dice()   *//* and for roll_count  */int main(void){    int dice,roll;    int sides;    srand((unsigned int) time(0)); /* randomize seed      */    printf("Enter the number of sides per die, 0 to stop.n");    while (scanf("%d", &sides) == 1 && sides > 0 )    {        printf("How many dice?n");        if ((status =scanf("%d", &dice)) != 1)        {            if (status == EOF)                break;             /* exit loop           */            else            {                printf("You should have entered an integer.");                printf(" Let's begin again.n");                while (getchar() != 'n')                    continue;     /* dispose of bad input */                printf("How many sides? Enter 0 to stop.n");                continue;         /* new loop cycle       */             }        }       roll = roll_n_dice(dice, sides);        printf("You have rolled a %d using %d %d-sided dice.n",               roll, dice, sides);        printf("How many sides? Enter 0 to stop.n");    }    printf("The rollem() function was called %d times.n",           roll_count);           /* use extern variable */    printf("GOOD FORTUNE TO YOU!n");    return 0;}
要与包含程序diceroll.c的文件一起编译该文件。可以把程序diceroll.c、diceroll.h和manydice.c都放在同一文件夹或目录中。运行该程序,下面是一个输出示例:

Enter the number of sides per die, 0 to stop.

6

How many dice?

2

You have rolled a 12 using 2 6-sided dice.

How many sides? Enter 0 to stop.

6

How many dice?

2

You have rolled a 4 using 2 6-sided dice.

How many sides? Enter 0 to stop.

6

How many dice?

2

You have rolled a 5 using 2 6-sided dice.

How many sides? Enter 0 to stop.

0

The rollem() function was called 6 times.

GOOD FORTUNE TO YOU!

因为该程序使用了srand()随机生成随机数种子,所以大多数情况下,即使输入相同也很难得到相同的输出。注意,manydice.c中的main()访问了定义在diceroll.c中的roll_count变量。

有3种情况可以导致外层while循环结束:side小于1、输入类型不匹配(此时scanf()返回0)、遇到文件结尾(返回值是EOF)。对于读取骰子的点数,该程序处理文件结尾的方式(退出while循环)与处理类型不匹配(进入循环的下一轮迭代)的情况不同。

可以通过多种方式使用roll_n_dice()。sides等于2时,程序模仿掷硬币,“正面朝上”为2,“反面朝上”为1(或者反过来表示也行)。很容易修改该程序单独显示点数的结果,或者构建一个骰子模拟器。如果要掷多次骰子(如在一些角色扮演类游戏中),可以很容易地修改程序以输出类似的结果:
Enter the number of sets; enter q to stop.18How many sides and how many dice?6 3Here are 18 sets of 3 6-sided throws.  12  10   6   9   8  14   8  15   9  14  12  17  11   7  10  13   8  14How many sets? Enter q to stop.q
rand1()或rand()(不是rollem())还可以用来创建一个猜数字程序,让计算机选定一个数字,你来猜。读者感兴趣的话可以自己编写这个程序。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表