小游戏中时常要用到随机数,今天就来谈谈这个所谓的“随机”。
我们要使用随机数(严格意义上是伪随机)的话,C++ 中就有 rand()
来提供了这一操作。
rand()
返回值是整数。在不同系统的编译器下,返回值的范围不同,我们姑且认为足够我们使用。
设我们要获取数 xxx,逐步推导:
rand()%101
;rand()%100+1
;rand()%(r-l+1)+l
。可现实总是不尽如人意:
为什么每次随机出来的序列都是一样的呢?这里我们就要讲到下面的东西了——
毕竟是伪随机,所以每次生成的随机序列需要有一个初始的随机种子(无符号整数),srand()
提供了这一操作。
比如设置随机种子为 114514114514114514,可以写成 srand(114514);
。
然而——
这意味着种子要随机。
time()
返回从 1970.1.11970.1.11970.1.1 至今的秒数,参数直接填 NULL
或 000(也就是空指针)即可。
设置为种子,也就是 srand(time(0));
。
效果显著:
如果有一个数组 aaa,如何让其进行随机排列呢?
C++ 有函数 random_shuffle()
。
参数和用法与 sort()
类似,直接调用即可。
示例代码:
#include
using namespace std;int main()
{srand(time(0)); int n,a[105];cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}random_shuffle(a+1,a+n+1);for(int i=1;i<=n;i++){cout<
效果:
给定边长 nnn,要求生成一个随机 01 矩阵。
示例代码:
#include
using namespace std;int main()
{srand(time(0)); int n;cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cout<
效果:
给定 nnn,要求生成 nnn 个区间 [l,r](l≤r)[l,r](l\le r)[l,r](l≤r),并且这些区间是 [1,n][1,n][1,n] 的子区间。
每次分别对于 l,rl,rl,r 随机,然后调整 l,rl,rl,r 大小位置。
示例代码:
#include
using namespace std;int main()
{srand(time(0)); int n;cin>>n;for(int i=1;i<=n;i++){int l=rand()%n+1,r=rand()%n+1;if(l>r) swap(l,r);//防止 l>rcout<
效果:
给定 nnn 和 kkk,要求生成 nnn 个 [0,n][0,n][0,n] 的 kkk 位浮点数(不可以有后缀 000)。
分成整数部分和小数部分考虑。
整数部分生成 [0,n][0,n][0,n] 的整数,小数部分生成 kkk 位 [0,9][0,9][0,9] 的数(在位数允许时,可以生成一个 [0,10k−1][0,10^k-1][0,10k−1] 的整数代替小数)。
当然,要特判整数为 nnn 的情况。若小数部分 >0>0>0,就不在 [0,n][0,n][0,n] 内了。
处理后缀 000 时,只要把其存进字符串处理即可。
示例代码:
#include
using namespace std;int main()
{srand(time(0)); int n,k;cin>>n>>k;for(int i=1;i<=n;i++){int d=rand()%(n+1);cout<cout<s+=(char)(rand()%10+48);}while(s[s.size()-1]=='0'&&s.size()>2) s.erase(s.size()-1);//防止后缀 0cout<
效果:
给定 n,l,r(l,r∈Z,l≤r)n,l,r(l,r\in\mathbb{Z},l\le r)n,l,r(l,r∈Z,l≤r),要求生成 nnn 个整数 x(x∈[l,r])x(x\in[l,r])x(x∈[l,r])。
可能含有负数,该怎么办呢?
分三类讨论:
-
,然后生成 [∣r∣,∣l∣][|r|,|l|][∣r∣,∣l∣] 范围的整数。-
,生成 [0,∣l∣][0,|l|][0,∣l∣] 的整数。注意以上操作中输出 -0
的情况要处理一下。
示例代码:
#include
using namespace std;int main()
{srand(time(0)); int n,l,r;cin>>n>>l>>r;while(n--){if(l<=r&&r<=0){int d=rand()%(abs(l)-abs(r)+1)+abs(r);if(d) cout<<'-';//防止 -0cout<int f=rand()%2;if(f) cout<int d=rand()%(abs(l)+1);if(d) cout<<'-';//防止 -0cout<
效果:
那这次的介绍到尾声了。有很多像模拟退火、随机调整等随机化算法,在这里不再赘述,感兴趣的读者可以查阅相关资料学习一下。随机化是游戏中重要的操作之一,相信读者已经有所收获,点个赞或者关注我一下吧,谢谢!