C++游戲教程基本技巧之隨機(jī)化詳解
0. 引言
小游戲中時(shí)常要用到隨機(jī)數(shù),今天就來談?wù)勥@個(gè)所謂的“隨機(jī)”。
1. 隨機(jī)數(shù) rand()
我們要使用隨機(jī)數(shù)(嚴(yán)格意義上是偽隨機(jī))的話,C++ 中就有 rand()
來提供了這一操作。
rand()
返回值是整數(shù)。在不同系統(tǒng)的編譯器下,返回值的范圍不同,我們姑且認(rèn)為足夠我們使用。
設(shè)我們要獲取數(shù)x,逐步推導(dǎo):
當(dāng)x∈[0,100] 時(shí),可以寫成 rand()%101;
當(dāng) x∈[1,100] 時(shí),可以轉(zhuǎn)化為x′+1(x′∈[0,99]),寫成 rand()%100+1;
當(dāng)x∈[l,r] 時(shí),可以轉(zhuǎn)化為x′+l(x′∈[0,r−l]),寫成 rand()%(r-l+1)+l。
可現(xiàn)實(shí)總是不盡如人意:
為什么每次隨機(jī)出來的序列都是一樣的呢?這里我們就要講到下面的東西了
2. 設(shè)置隨機(jī)種子 srand()
畢竟是偽隨機(jī),所以每次生成的隨機(jī)序列需要有一個(gè)初始的隨機(jī)種子(無符號(hào)整數(shù)),srand()
提供了這一操作。
比如設(shè)置隨機(jī)種子為114514,可以寫成 srand(114514);
。
然而
這意味著種子要隨機(jī)。
3. 時(shí)間 time()
time()
返回從 1970.1.1 1970.1.1 1970.1.1 至今的秒數(shù),參數(shù)直接填 NULL
或 0 0 0(也就是空指針)即可。
設(shè)置為種子,也就是 srand(time(0));
。
效果顯著:
4. 隨機(jī)排列 random_shuffle()
如果有一個(gè)數(shù)組 a a a,如何讓其進(jìn)行隨機(jī)排列呢?
C++ 有函數(shù) random_shuffle()
。
參數(shù)和用法與 sort()
類似,直接調(diào)用即可。
示例代碼:
#include<bits/stdc++.h> 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<<a[i]<<' '; } return 0; }
效果:
5. 隨機(jī)基本案例
5-1. 隨機(jī) 01 矩陣
給定邊長(zhǎng)n,要求生成一個(gè)隨機(jī) 01 矩陣。
示例代碼:
#include<bits/stdc++.h> 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<<rand()%2; } cout<<endl; } return 0; }
效果:
5-2. 隨機(jī)區(qū)間
給定n,要求生成n個(gè)區(qū)間[l,r](l≤r),并且這些區(qū)間是[1,n]的子區(qū)間。
每次分別對(duì)于l,r隨機(jī),然后調(diào)整l,r大小位置。
示例代碼:
#include<bits/stdc++.h> 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>r cout<<l<<' '<<r<<endl; } return 0; }
效果:
5-3. 隨機(jī)浮點(diǎn)數(shù)
給定n和k,要求生成n個(gè)[0,n] 的k位浮點(diǎn)數(shù)(不可以有后綴0)。
分成整數(shù)部分和小數(shù)部分考慮。
整數(shù)部分生成[0,n] 的整數(shù),小數(shù)部分生成k位 [0,9] 的數(shù)(在位數(shù)允許時(shí),可以生成一個(gè)[0,10k−1] 的整數(shù)代替小數(shù))。
當(dāng)然,要特判整數(shù)為n的情況。若小數(shù)部分>0,就不在[0,n]內(nèi)了。
處理后綴0時(shí),只要把其存進(jìn)字符串處理即可。
示例代碼:
#include<bits/stdc++.h> 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<<d; if(d==n) { cout<<endl; continue; } string s="."; for(int j=1;j<=k;j++) { s+=(char)(rand()%10+48); } while(s[s.size()-1]=='0'&&s.size()>2) s.erase(s.size()-1);//防止后綴 0 cout<<s<<endl; } return 0; }
效果:
5-4. 隨機(jī)整數(shù)
給定n,l,r(l,r∈Z,l≤r),要求生成n個(gè)整數(shù)x(x∈[l,r])。
可能含有負(fù)數(shù),該怎么辦呢?
分三類討論:
1.當(dāng)l≤r≤0 時(shí),先輸出 -
,然后生成[∣r∣,∣l∣] 范圍的整數(shù)。
2.當(dāng)l≤0≤r 時(shí),先隨機(jī)t=0或1來確定符號(hào)。
- 當(dāng)t=0時(shí),輸出
-
,生成[0,∣l∣] 的整數(shù)。 - 當(dāng)t=1時(shí),生成[0,r]的整數(shù)。
3.當(dāng)0≤l≤r時(shí),直接生成[l,r] 的整數(shù)。
注意以上操作中輸出 -0
的情況要處理一下。
示例代碼:
#include<bits/stdc++.h> 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<<'-';//防止 -0 cout<<d; } else if(l<=0&&0<=r) { int f=rand()%2; if(f) cout<<rand()%(r+1); else { int d=rand()%(abs(l)+1); if(d) cout<<'-';//防止 -0 cout<<d; } } else cout<<rand()%(r-l+1)+l; puts(""); } return 0; }
效果:
以上就是C++游戲教程基本技巧之隨機(jī)化詳解的詳細(xì)內(nèi)容,更多關(guān)于C++隨機(jī)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++基礎(chǔ)知識(shí)之運(yùn)算符重載詳解
這篇文章主要為大家詳細(xì)介紹了C++基礎(chǔ)知識(shí)之運(yùn)算符重載,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-02-02C語言的字符串函數(shù),內(nèi)存函數(shù)筆記詳解
這篇文章主要給大家介紹了關(guān)于C語言字符串/內(nèi)存的相關(guān)函數(shù),文中通過示例代碼總結(jié)的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C語言具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2021-09-09Cocos2d-x UI開發(fā)之菜單類使用實(shí)例
這篇文章主要介紹了Cocos2d-x UI開發(fā)之菜單類使用實(shí)例,本文的代碼中含有詳細(xì)注釋,需要的朋友可以參考下2014-09-09詳解state狀態(tài)模式及在C++設(shè)計(jì)模式編程中的使用實(shí)例
這篇文章主要介紹了state狀態(tài)模式及在C++設(shè)計(jì)模式編程中的使用實(shí)例,在設(shè)計(jì)模式中策略用來處理算法變化,而狀態(tài)則是透明地處理狀態(tài)變化,需要的朋友可以參考下2016-03-03