利用rand()和srand()产生随机数编写猜数字游戏

目录

1.rand和srand介绍

2.如何使用rand和srand

3.常见到的问题

4.用C语言实现猜数字游戏


1.rand和srand介绍

在C语言中,当我们需要产生伪随机数的时候,我们往往会使用rand()和srand()两个函数,他们是一对相辅相成的函数。在MSDN中搜索rand函数,你会看到如下图所示的内容:

使用rand函数能够生成随机数,但这个数并非完全随机,而是伪随机数。

  • 在使用之前我们需要引一个名为stdlib的库函数。
  • 在调用之后,rand函数将会返回一个范围为0到rand_MAX的伪随机整数,因此rand不会产生错误返回。

int rand( void )告诉我们,rand函数无需传参。

  • 但在调用rand之前,需要我们使用srand函数为伪随机数生成器设定种子(seed)

因此srand()的作用便是为rand()设定种子,种子的作用我们会在第二点讲到。

2.如何使用rand和srand

由于rand函数无需传参,调用起来也比较方便,因此如果你想生成随机数并且打印在屏幕上,只需要写上这么一行代码就可以了

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int ret = rand();      //使用ret接受一个返回值
	printf("%d\n", ret);   //将rand()的返回值打印出来
	return 0;
}

运行得到的结果如下,我们这里使用rand函数返回了一个41的随机值。

但是当我们再次运行程序时,发现所产生的随机数仍然时41,这明显与我们想要输出的所谓“随机数不同”,究其原因:

rand 是一个固定的迭代函数,输出随机数的原理是对一个初始值不停嵌套计算后进行输出。输出的序列有不错的统计性质,所以叫伪随机数。 然而,在不进行设置时,这个初始值始不会发生改变,这意味着每次得到的结果都是一样的。srand就是对这个初始值进行设置的一个函数。

srand()为初始化随机数发生器,需要在rand()之前调用。

其参数称作“种子seed”,类型是unsigned int,作用于rand()产生随机数时的过程。当我们给的参数为1时,下面代码得到的结果是41,和之前的结果一致。说明在没有调用srand之前,编译器默认给了一个srand(1)。

在改变seed的值后,可以看到rand产生的随机数发生了变化,这进一步印证了 rand产生的随机数是借于srand的seed不断改变而实现的。seed的值不变,所产生的随机数也不变。因此不难看出,我们需要一个不断变化的seed来确保每次rand产生的数是不同的。

这里我们通常使用会使用time(NULL)或time(0)来表示变化的种子,time(0)的返回的是从1970 UTC Jan 1 00:00到当前时刻的秒数,为unsigned int类型,而使用time(NULL),通常需要将其强制类型转换:

srand((unsigned int)time(NULL));

当我们需要不断生产随机数时,往往将rand函数放在循环中,但结果往往出乎我们意料。

使用下面这段代码我们循环打印了15个随机数

可这样一段代码所得到的所有随机数居然是相同的! 

其原因是:

  • 当把srand放在循环体内部时,每一次进入循环的时间是小于1s的,这样每次都为srand都提供了相同的seed。这样不断地重置一个相同地seed,等价于使用了一个固定的随机数seed。

 正确地做法是将srand()放在循环外部:

 因此,rand()和srand()的标准用法是:

  • 给srand一个不断变化的参数,通常用时间戳
  • 将srand放在循环外部
  • 将rand放在循环内部

3.常见到的问题

有时我们需要给出在一定范围内的随机数,可以使用C语言中的求余“%”和除法“/”运算。

例如需要产生[0,1]内的随机数时,可以考虑如下代码:

rand_num = rand()/RAND_MAX;

需要产生[1,100]的随机数时 ,可以考虑如下代码:

rand_num= rand()%100+1;

4.用C语言实现猜数字游戏

学习完rand()和srand()之后,我们可以用C语言编写一个猜数字的游戏:

//猜数字游戏实现
//1.电脑随机生成一个1~100之间的数
//2.玩家输入数字,如果命中,输出“猜中了”;不命中,输出“猜大了”或“猜小了”;直至猜中为止
//3.游戏可以一直玩

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void menu1()
{
	printf("*******************\n");
	printf("*****1.开始游戏*****\n");
	printf("*****0.退出游戏*****\n");
	printf("*******************\n");
}

void menu2()
{
	printf("*******************\n");
	printf("*****1.再来一局*****\n");
	printf("*****0.退出游戏*****\n");
	printf("*******************\n");
}
void game()
{
	int i = rand()%100+1;  
	//printf("%d\n", i);   
	while (1)              
	{
		int guess = 0;
		scanf("%d", &guess);
		if (guess < i)
		{
			printf("猜小了\n\n");
		}
		else if (guess > i)
		{
			printf("猜大了\n\n");
		}
		else if (guess == i)
		{
			printf("恭喜你,猜对了!\n\n");
			break;
		}
	}
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	int flag = 0;
	do
	{
		flag++;
		if(flag==1)
		{
			menu1();
		}
		else
		{
			menu2();
		}
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 0:
			printf("退出游戏\n");
			break;
		case 1:
			printf("请猜一个数字:>");
			game();
			break;
		default:
			printf("输入错误\n");
		}
		
	} while (input);
	return 0;
}

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值