对于C语言初学者来说,当我们的翻开课本咕叽咕叽读完C语言概述后,就会紧接着面临C语言控制语句(顺序,选择和循环),然后不约而同都会面临用三大控制语句编写猜数字游戏的问题。这的确是一个比较容易编写的小游戏,但同时也是一个很好练习机会,不仅仅让我们充分利用所学知识完成对程序的编写,同时也引导我们思考如何用C语言生成随机数。
首先我们要了解一下什么是猜数字。顾名思义,就是随机指定一个数字,然后让人猜数,通过反馈的信息(猜大了或者猜小了)来逐渐锁定最终值。
定义好我们程序的目标后,我们就要开始对程序进行设计,要有一个明确的步骤。
1.首先我们需要提升游玩者体验,就应该有一个菜单。
2.其次游玩者可能需要循环往复玩这个游戏,我们就应该将游戏放入循环体内。
3.最后才是我们对于游戏具体的设计。在游戏具体设计内,我们需要让系统生成一个随机数,然后让游玩者输入一个数字,通过对二者的比较,反馈信息,以便让游玩者逐渐接近具体目标。
#define _CRT_SECURE_NO_WARNINGS //防止sancf报安全性错误
#include //time()函数头文件
#include //rand(),srand()函数头文件
#include //printf(),scanf()函数头文件
void menu()//进入游戏对菜单的打印
{
printf("***************************\n");
printf("******** 1. play **********\n");
printf("******** 0. exit **********\n");
printf("***************************\n");
}
int main()
{
int input = 0;//定义一个变量input,存放用户输入的值
do
{ //函数可以简单理解为对一段代码的封装。
menu();//这是菜单的打印,利用函数可以避免主函数过于冗长
printf("请选择(1/0):>");//让用户输入1开始玩游戏,0则退出游戏
scanf("%d", &input);
switch (input)
{
case 1:
game();//游戏具体实现
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误\n");
}
} while (input);//0为假,非0为真,真则会重新进入循环体,假则会退出循环体
return 0;
}
然后就是对游戏具体实现的思考,首先我们要生成一个随机数,现在的C编译器都提供了一个基于ANSI标准的伪随机数发生器函数,用来生成随机数,它们就是rand()和srand()函数。
void game()
{
srand((unsigned int)time(NULL));//为rand()函数重新“播种”,使得rand()产生随机值(rand()产生的随机值我们称为“种子”)发生变化 (具体我们在第二节详细解释)
int ret = rand()%100+1;//生成的随机值1-100
int guess = 0;
while (1)
{
printf("请猜数字:>");
scanf("%d", &guess);
if (guess > ret)
{
printf("猜大了\n");
}
else if (guess < ret)
{
printf("猜小了\n");
}
else
{
printf("猜对了\n");
break;
}
}
}
但实际上我们不太喜欢将rand()和srand()函数放得太近,因为这样子反复运行程序还是容易使得rand()函数产生相近的值,所以我们比较提倡将srand()函数放到主函数中,事实上每次用到rand()函数只需要srand()函数“播种”一次即可。接下来展示就是猜数字游戏所示全部代码:
#define _CRT_SECURE_NO_WARNINGS //防止sancf报安全性错误
#include //time()函数头文件
#include //rand(),srand()函数头文件
#include //printf(),scanf()函数头文件
void game()
{
int ret = rand()%100+1;//生成的随机值1-100
int guess = 0;
while (1)
{
printf("请猜数字:>");
scanf("%d", &guess);
if (guess > ret)
{
printf("猜大了\n");
}
else if (guess < ret)
{
printf("猜小了\n");
}
else
{
printf("猜对了\n");
break;
}
}
}
void menu()//进入游戏对菜单的打印
{
printf("***************************\n");
printf("******** 1. play **********\n");
printf("******** 0. exit **********\n");
printf("***************************\n");
}
int main()
{
int input = 0;//定义一个变量input,存放用户输入的值
srand((unsigned int)time(NULL));//为rand()函数重新“播种”,使得rand()产生随机值(rand()产生的随机值我们称为“种子”)发生变化 (具体我们在第二节详细解释)
do
{ //函数可以简单理解为对一段代码的封装。
menu();//这是菜单的打印,利用函数可以避免主函数过于冗长
printf("请选择(1/0):>");//让用户输入1开始玩游戏,0则退出游戏
scanf("%d", &input);
switch (input)
{
case 1:
game();//游戏具体实现
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误\n");
}
} while (input);//0为假,非0为真,真则会重新进入循环体,假则会退出循环体
return 0;
}
接下来我们对刚刚展示的利用C语言生成随机数做一个具体解释。
现在的C编译器都提供了一个基于ANSI标准的伪随机数发生器函数,用来生成随机数,它们就是rand()和srand()函数。
然后我们用MSDN软件查看一下对于rand()和srand()函数的表述:
1.int rand( void )
Generates a pseudorandom number(生成伪随机数)
The rand function returns a pseudorandom integer in the range 0 to RAND_MAX(rand函数返回一个范围为0到RAND_MAX的伪随机整数)(C语言规定RAND_MAX值为32767)
此时我们编写一个代码尝试一下:
void main(void)
{
int i;
for (i = 0; i < 10; i++)
printf("%d ", rand());
printf("\n\n\n\n");
}
不难发现运行两次后,会重复出现一样的数字,这就违背了我们想要随机的本意。实际上,rand() 函数产生的随机数是伪随机数,是根据一个数值按照某个公式推算出来的,这个数值我们称之为“种子”,种子和随机数之间的关系是一种正态分布关系,种子在每次启动计算机时是随机的,但是一旦计算机启动以后它就不再变化了;也就是说,每次启动计算机以后,种子就是定值了,所以根据公式推算出来的结果(也就是生成的随机数)就是固定的。
返回MSDN软件继续查看关于rand()函数描述:
Use the srand function to seed the pseudorandom-number generator before calling rand.(在调用rand之前,使用srand函数为伪随机数生成器播种)
2.void srand( unsigned int seed )
Sets a random starting point.(设置随机起点)
而要让 srand()函数随机播种,我们则必须让参数是一个随机值,这就产生悖论。所以前辈们在实际开发中,就用时间作为参数,只要每次播种的时间不同,那么生成的种子就不同,最终的随机数也就不同。而要得到时间则又引出了另一个函数time()函数
3.time_t time( time_t *timer )
Gets the system time.(获取系统时间。)
time()函数返回类型为time_t,time_t 实际在C语言中被定义为长整型,而srand()函数参数为unsigned int(无符号整形),所以要强制类型转换,而且不需要为time()函数设置参数,故用空指针NULL代替。
最后我们得到srand()函数设置随机数起点写法
srand( (unsigned int)time( NULL ) );
最后我们试验一下:
#include
#include
#include
void main(void)
{
int i;
srand((unsigned int)time(NULL));
for (i = 0; i < 10; i++)
printf(" %6d\n", rand());
}
希望能够对你有所帮助,因为我也是第一次尝试写技术性博客,如有问题,烦请指正,谢谢你的阅览。