C语言中如何生成随机度高的随机数

rand函数

作用

在运行程序后被调用时返回一个 0 ~ 32767 间的随机数

语法

需要的头文件为:stdlib.h

#include<stdlib.h>

int main()
{
    int a = rand();
    return 0;
}

缺陷

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

int main()
{
    int i = 0;
    for (; i < 10; i++)//一个循环 10 次打印“随机值”的 for 语句
    {
        int a = rand();
        printf("%d\n", a);
    }


    return 0;
}

当我们反复运行以上程序不难发现,打印出的随机数顺序都是一样的,都是:

41
18467
6334
26500
19169
15724
11478
29358
26962
24464

于是我们需要引入 srand 函数

srand 函数

作用

用于给函数 rand 设置种子

不同种子下生成随机数的规则不一致

语法

需要的头文件为:stdlib.h

#include<stdlib.h>

int main()
{
    srand(unsigned int);//无符号的整型
    int a = rand();
    return 0;
}

示例

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

int main()
{
    srand(10);//将随机数种子设为 10
    int i = 0;
    for (; i < 10; i++)//一个循环 10 次打印“随机值”的 for 语句
    {
        int a = rand();
        printf("%d\n", a);
    }


    return 0;
}

我们将最开始的实例加上 srand 后发现,得到的”随机数“确实不一样了:

71
16899
3272
13694
13697
18296
6722
3012
11726
1899

但是如果生成随机数的种子不变,每次运行程序后生成的顺序仍然一样

也就是说我们需要用 srand 函数给 rand 函数生成一个随机数作为种子

我们需要生成一个随机数,但生成一个随机数需要一个随机数,所以我们要生成一个随机数作为随机数用来生成随机数(bushi

那这个问题该怎么解决呢?

time 函数

作用

获取当前时间戳

时间戳是什么?

以下来自百度百科:

时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。

 也就是说时间戳是在不断变化

语法

需要的头文件为:time.h

time(指针);

示例

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

int main()
{
    int a = time(NULL);//给 time 函数传递一个空指针
    printf("%d",a);
    
    return 0;
}

当每次运行以上程序后我们发现:打印出的值在不断增加

于是我们就可以用时间戳作为生成随机数的种子

实现完全随机

原理

正如上文所说:用时间戳作为生成随机数的种子

一个不当的实例

#include<Windows.h>//Sleep 函数的头文件
#include<time.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
    int b = 0;
    while (1)
    {
        unsigned int seed = time(NULL);//定义局部变量 seed,并将时间戳赋值给 seed
        
        srand(seed);//设置随机数种子
        
        b = rand();//获取随机数
        
        printf("%d\n", b);//打印出获取的随机数
        
        Sleep(1000);//暂停 1000ms ,也就是暂停 1s
    }

    return 0;
}

在这里我们无需过多关注 Sleep 函数和 Windows.h

以上程序运行后在屏幕上打印出的数字呈现某种连续性:

29772
29775
29779
29782
29785
29788
29792
29795
29798
29801
29805
29808
...

这是由于:

以上程序将设置随机数种子的部分放在了循环内,

导致每次设置随机数种子后只打印该种子下的第一个随机数,

随后又重新设置种子

于是,我们得出结论:在需要生成随机数时,设置随机数种子的部分在整个程序中最好只运行一次

对于以上实例,我们只要将设置随机数种子的部分放至循环体外部即可

正确的实例

将设置随机数种子的部分放在循环体外,使得运行一次程序只设置一次种子

#include<Windows.h>
#include<time.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
    unsigned int seed = time(NULL);
    srand(seed);//将设置随机数种子的部分放在循环体外,使得运行一次程序只设置一次种子
    int b = 0;
    while (1)
    {
        b = rand();
        
        printf("%d\n", b);
        
        Sleep(1000);
    }

    return 0;
}

某次运行结果:

30846
14300
24092
15809
26965
513
13552
30653
25913
24850
11981
5943
26837
5208
11753
...

限制范围

原理

通过取模操作可以使生成的这个范围在 0~32767 间的数字范围缩小

示例( r 为生成的随机数)

r % b

该式的结果即为 r 除以 b 的余数,可能取值为:0,1,2...b - 2,b - 1

可以得到范围限制在 [ 0 , n - 1 ] 的随机数

如果要限制的范围最小值不为 0 ,那么可以再加上一个数

r % b + c

可以得到范围限制在 [ c , b - 1 + c ] 的随机数

示例

#include<time.h>
#include<stdlib.h>
#include<stdio.h>
int main()
{
	srand((unsigned int)time(NULL));
	int a = 0;
	int i = 0;
	int b = 100;
	int c = 10;
	for (; i < 100; i ++)
	{
		a = (rand() % b + c);
		printf("%d\n", a);
	}


	return 0;
}

以上的 b 为区间宽度 + 1,c 为区间最小值

会将 a 的范围限制在 [10,109]

例如:要使得随机值范围在 [15,300] 之间的话

c == 15

计算可知区间长度 b == 275 + 1 == 276

a = (rand() % 276 + 15);

应用

这种方法通常在写一些小游戏比如扫雷、三子棋(井字棋)、猜数游戏等。

都看到这了,不考虑点点关注什么的......

如果你对上面提到的几个小游戏感兴趣,那么我后面也会出相关的文章教程哦~

所以现在就______我,防止以后找不到

(疯狂暗示)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值