C语言rand随机数知识解析和猜数字小游戏

rand随机数

rand

C语言中提供了一个可以随机生成一个随机数的函数:rand()

函数原型:

c 复制代码
int rand(void);

rand函数返回的值的区间是:0~RAND_MAX(32767)之间。大部分编译器都是32767。

c 复制代码
#include<stdlib.h>
int main()
{
	printf("%d", RAND_MAX);
	return 0;
}

要想使用这个rand函数需要包含头文件:#include<stdlib.h>

但是rand函数直接使用是提供的伪随机数,这个随机数是有有迹可循的,没有实现真正的随机,这是因为它生成这个数是基于一个确定的算法而生成的。

c 复制代码
int main()
{
	int x = rand();
	int y = rand();
	printf("%d  %d\n", x, y);

	return 0;
}

执行第一次:

执行第二次

可以看出两次执行的随机数相同,所以单纯使用rand函数生成不了真正的随机数。

所以,要想真正实现随机生成,需要使rand() 函数基于一个种子(seed)来生成 ,默认情况下,这个种子是1。

每次调用 rand(),它都会基于前一个随机数生成下一个随机数。这意味着如果你多次使用相同的种子调用 rand(),你会得到相同的随机数序列。

srand

C语言又提供了一个初始化随机数的函数:srand()

函数原型:

c 复制代码
void srand(unsigned int seed);

注意:seed的数据类型是unsigned int

在程序中显示有srand函数确定一个种子,只要种子在变化,rand()函数生成的随机数也就在变化。也就是说只要srand的种子是随机的,rand就能生成随机数,在生成随机数的同时又生成一个随机数,这就矛盾了。所以种子的随机不能由我们来确定,所以我们交给time()函数

time

在程序中我们一般使用程序运行时间作为种子的,因为时间时刻在发生变化,就省去我们去随机种子了。

在C语言中有一个表示时间的函数:time()

函数原型:

c 复制代码
time_t time(time_t* timer);

timer是一个可选的参数,如果提供了这个参数,那么函数会将返回的时间(从1970年1月1日00:00:00 开始到现在的秒数)存储在这个参数指向的变量中。如果这个参数是NULL,那么函数只返回时间值而不存储它。

要想使用time(),需要头文件:#include<time.h>

代码实现:

c 复制代码
#include<time.h>
#include<stdio.h>
int main() {
	printf("%d",time(NULL));
	return 0;
}

这是一个时间戳,就是从1970年1月1日00:00:00 开始到现在的秒数。

  1. 先在浏览器中找一个可以转换时间戳的网站

  2. 将代码结果复制并放在转换工具里,就可以看到当前时间

所以我们用time()函数的返回值充当srand()函数的参数,就可以返回一个随机值了。

c 复制代码
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
int main() {
	srand((unsigned int)time(NULL));
	int x = rand();
	int y = rand();
	printf("%d %d\n", x, y);
	return 0;
}

执行第一次:

执行第二次:

这样就可实现随机值生成了。

设置随机数的范围

当我们可以生成随机数的时候就可以设置随机数生成范围了,上文说过随机数生成范围是0---32767,我们可以要rand()%100 就可以得到得到0---99之间的数了,这是因为不管什么数对100求余,只能得到0---99的数。

所以:

生成0~99之间的随机数

c 复制代码
rand() %100;

生成1~100之间的随机数

c 复制代码
rand() %100+1;

生成a~b之间的随机数

c 复制代码
a + rand() % (b-a+1);

猜数字小游戏

问题:

写一个随机猜数字小游戏,只有10次机会,超过则失败

规则

  1. 电脑自动生成1~100的随机数
    2.玩家猜数字,猜数字过程中,根据数据的大小给出大了或者小了的反馈,在10次猜测中,猜对了,则游戏结束。

代码实现

c 复制代码
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
void interface(void) {//游戏界面
	printf("******************\n");
	printf("****1 游戏开始****\n");
	printf("****2 退出游戏****\n");
	printf("******************\n");
}
void game(void) {
	int type = 10;//只有10次猜测机会
	int result = rand() % 100 + 1;//产生1~100之间的随机数
	int guess = 0;
	while (type) {//只有还有机会时才进入循环
		printf("还有%d次机会", type);
		printf("请猜测数字:>");
		scanf("%d", &guess);
		if (guess < result) {
			printf("猜小了\n");
		}
		else if (guess > result) {
			printf("猜大了\n");
			}
		else {
			printf("恭喜!猜对了\n");
			break;
		}
		type--;//while循环一次机会少一次
	}
	if (type == 0) {
		printf("机会用完了,答案是:%d\n", result);
	}
}
int main() {//控制是玩游戏还是退出游戏
	srand((unsigned int)time(NULL));//设置种子,以确保生成正确的随机数
	int n = 0;
	do {
		interface();//调用界面函数
		printf("请选择:>");
		scanf("%d", &n);//选则游戏模式
		switch (n) {
		case 1:
			game();
			break;
		case 2:
			printf("游戏结束\n");
			break;
		default :
			printf("选择错误,重新选择:>\n");
			break;
		}
	} while (n);//当选则了再进入循环
	return 0;
}

易错点

这段代码可能有几个易错点,我一一指出:

如果把产生随机数的代码放在循环里面,那么每次猜测都是一个新的随机数,那么只有一次机会可以猜测。

这里把大小于关系写错了,那么根据提示就永远也猜不出答案了。

这里把种子函数放在循环里面了,这样做的后果是随机生成的值相似甚至相同。这是因为time(NULL) 返回的时间值在两次迭代之间几乎没有变化,导致种子几乎相同,进而产生相似的随机数序列。

可以代码验证一下:

c 复制代码
int main() {
	while (1) {
		srand((unsigned int)time(NULL));
		printf("%d\n", rand());
	}

	return 0;
}

所以写这个代码时应该注意。

/考研势在必行/

相关推荐
一个小坑货3 分钟前
Cargo Rust 的包管理器
开发语言·后端·rust
bluebonnet278 分钟前
【Rust练习】22.HashMap
开发语言·后端·rust
古月居GYH8 分钟前
在C++上实现反射用法
java·开发语言·c++
在下不上天33 分钟前
Flume日志采集系统的部署,实现flume负载均衡,flume故障恢复
大数据·开发语言·python
陌小呆^O^1 小时前
Cmakelist.txt之win-c-udp-client
c语言·开发语言·udp
I_Am_Me_1 小时前
【JavaEE进阶】 JavaScript
开发语言·javascript·ecmascript
重生之我是数学王子1 小时前
QT基础 编码问题 定时器 事件 绘图事件 keyPressEvent QT5.12.3环境 C++实现
开发语言·c++·qt
Ai 编码助手1 小时前
使用php和Xunsearch提升音乐网站的歌曲搜索效果
开发语言·php
学习前端的小z1 小时前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
神仙别闹1 小时前
基于C#和Sql Server 2008实现的(WinForm)订单生成系统
开发语言·c#