游戏代码
#include
#include
#include
int main()
{
int no;//读取的值
int ans;//目标数字
srand(time(NULL));//设定随机数的种子
ans = rand() % 1000;//生成0~999的随机数
printf("请猜一个0~999的整数。\n\n");
do {
printf("是多少呢:");
scanf("%d", &no);
if (no > ans)
printf("\a再小一点。\n");
else if (no < ans)
printf("\a再大一点。\n");
} while (no != ans);
printf("回答正确。\n");
return 0;
}
随机数生成
#include
C 库函数 int rand(void) 返回一个范围在 0 到 RAND_MAX 之间的伪随机数。
RAND_MAX 是一个常量,它的默认值在不同的实现中会有所不同,但是值至少是 32767。
这个函数生成的随机数是int型的整数。在所有编译环境中其最小值都为0,但最大值取决于编译环境,所以我们用
#define RAND_MAX 0x7fff //十六进制0x7fff 即十进制32767
下面是 rand() 函数的声明。
1 |
|
该函数返回一个范围在 0 到 RAND_MAX 之间的伪随机数整数。
#include
#include
int main()
{
//int a=RAND_MAX;
int retry = 0;//再运行一次?
//srand(time(NULL));
printf("生成0~%d的随机数\n", RAND_MAX);
do {
printf("\n生成了随机数:%d\n", rand());
printf("再运行一次?……(0)否(1)是:");
scanf("%d", &retry);
} while (retry);
return 0;
}
每一次运行上面的代码,实际生成的随机数序列是一样的。rand函数生成的叫做伪随机数的随机数。伪随机数看起来很像随机数,却是基于某种规律生成的。因为能预测接下来会生成什么数值,所以才叫做伪随机数。真正的随机数是无法预测接下来会生成什么数值的。
rand函数是对一个叫做“种子”的基准值加以运算来生成随机数的。之所以先前每次运行程序都会生成同一个随机数序列,是因为rand函数的默认种子是常量1.要生成不同的随机数,就必须改变种子的值。
负责执行这项任务的就是srand函数
#include
C 库函数 void srand(unsigned int seed) 播种由函数 rand 使用的随机数发生器。
给后续调用的rand函数设置一个种子(seed),用于生成新的伪随机数序列。如果同一个种子的值调用本函数,就会生成相同的伪随机数序列。如果在调用本函数之前调用了rand函数,就相当于程序在一开始调用了本函数,把seed设定成了1,最后会生成一个种子值为1的序列。
下面是 srand() 函数的声明。
1 |
|
该函数不返回任何值。
比如,我们调用了srand(50)。这样,之后调用rand函数就会利用设定的新种子值50来生成随机数。
当种子为1时,在最初调用rand函数时生成的是41,再调用生成18467,接下来是6334……
如果种子值是50,则会依次生成201、20851、6334……
#include
#include
int main()
{
int retry = 0;//再运行一次?
//srand(50);//读者自行可去掉该行注释运行
printf("生成0~%d的随机数\n", RAND_MAX);
do {
printf("\n生成了随机数:%d\n", rand());
printf("再运行一次?……(0)否(1)是:");
scanf("%d", &retry);
} while (retry);
return 0;
}
由上可知,一旦确定了种子的值,之后生成的随机数序列也就确定了。因此想要每次运行程序时都能生成不同的随机数序列,就必须把种子值本身从常量变成随机数。
然而,为了生成随机数而需要随机数,这本身很矛盾。
我们一般使用的方法是把运行程序时的时间当做种子。如下面程序中就使用了这个方法。
#include
#include
#include
int main()
{
//int a=RAND_MAX;
int retry = 0;//再运行一次?
srand(time(NULL));
printf("生成0~%d的随机数\n", RAND_MAX);
do {
printf("\n生成了随机数:%d\n", rand());
printf("再运行一次?……(0)否(1)是:");
scanf("%d", &retry);
} while (retry);
return 0;
}
关于获取当前时间所使用的time函数,下面开始介绍。
当然也可以把srand(time(NULL))当成固定的一部分即可(#include
#include
获取当前时间
获取当前日历时间作为类型time_t(其实就是unsigned long)的值。
函数返回此值,如果参数不是空指针,它还将此值设置为计时器指向的对象。
返回的值通常表示UTC 1970年1月1日00:00小时后的秒数(即当前unix时间戳)。尽管库可能使用不同的时间表示:可移植程序不应直接使用此函数返回的值,而是始终依赖于对标准库的其他元素的调用来将其转换为可移植类型(如localtime、gmtime或difftime)。
1 |
time_t time ( time_t* timer ); |
1.传递 time_t* 类型的指针时,返回time_t类型的到该指针指向的变量,不需要参数进行接收返回值。
2.用 time_t 类型变量接收时,可以传递NULL指针,返回值直接存放在该变量。
srand((unsigned int)time(NULL));
rand函数生成的值范围是0~RAND_MAX,话虽如此,但我们需要的随机数不会每次都恰好在这个范围内。
一般情况下,我们需要的是某个特定范围内的随机数。如果我们需要“大于等于0且小于等于10”的随机数,就可以向下面这样求出。
rand() % 11; //生成大于等于0且小于等于10”的随机数
这里使用的方法是把非负整数的值除以11,就得到余数为0,1,…,10。
这里要注意不要把非负整数值错除以10。用10除得到的余数是0,1,…,9,无法生成10。
利用上面的方法,我们还可变更目标数字的范围。下面举两个例子。
把目标数字定为1~999
ans = 1 + rand() % 999; //生成1~999的随机数
把目标数字定为3位数的整数(100~999)
ans = 100 + rand() % 900; //生成100~999的随机数
小结
生成随机数之前要基于当前时间设定“种子”的值。
#include
#include
//
srand(time(NULL)); //设定随机数种子
在最初调用rand函数之前先调用srand函数(至少调用一次,调用次数不限)。
如果没有做上述准备工作,那么种子的值就会默认为1,会生成相同的随机数序列。
一旦调用rand函数,就会得到一个大于等于0且小于等于RAND_MAX的随机数。RAND_MAX的值取决于编译环境,即大于等于32767
此外,如果想把随机数定在某个特定范围内,可以像下面这样操作。
rand() % (a + 1); //大于等于0且小于等于a的随机数
b + rand() % (a + 1); //大于等于b且小于等于b+a的随机数
后记
用随机数函数抽签决定学院安排的某些活动,真是太方便了