遊戲開發——隨機數和概率在遊戲中的使用

轉載至  【Visual C++】遊戲開發筆記十七 遊戲基礎算法(一) 遊戲隨機系統初步

計算機中一般不能產生絕對隨機的隨機數。計算機產生隨機數的過程,是根據一個數(我們可以稱它爲種子)爲基準以某個遞推公式推算出來的一系列數,當這系列數很大的時候,就符合正態公佈,從而相當於產生了隨機數,但這不是真正的隨機數,當計算機正常開機後,這個種子的值是確定的,除非你對系統進行了更改。即計算機一般情況下只能生成相對的隨機數,即僞隨機數。

在很多時候,我們會使用rand()函數與srand()配合來達到產生隨機數的效果,srand初始化隨機種子,rand產生隨機數。

一、隨機數發生器rand()函數的用法

函數名: rand
功 能: 隨機數發生器
用 法: int rand(void);
所在頭文件: stdlib.h
函數說明 :
▲rand()的內部實現是用的線性同餘法,它不是真的隨機數,因其週期特別長,故在一定的範圍裏可看成是隨機的。
▲這種僞隨機數是由小M多項式序列生成的,其中產生每個小序列都有一個初始值,即隨機種子。(注意: 小M多項式序列的週期是65535,即每次利用一個隨機種子生成的隨機數的週期是65535,當你取得65535個隨機數後它們又重複出現了。)
▲目前,計算機中用來產生隨機數的算法基本上都是“線性同餘”法。rand()返回一隨機數值的範圍在0至RAND_MAX 間。RAND_MAX的範圍最少是在32767之間(int)。
▲用unsigned int 雙字節是65535,四字節是4294967295的整數範圍。0~RAND_MAX每個數字被選中的機率是相同的。
▲用戶未設定隨機數種子時,系統默認的隨機數種子爲1。
▲rand( )產生的是僞隨機數字,每次執行時是相同的;若要不同,用函數srand()初始化它。

//MyRand01.cpp
#include <iostream>  
using namespace std;  
#include   <stdlib.h>      
#include   <time.h>   
#define MIN 1    //隨機數產生的範圍      
#define MAX 10  

int main()     
{   
    int i;   
    srand((unsigned)time(0));  
    cout<<"10個隨機數從 "<<MIN<<  
          " 到 "<<MAX<<" :\n"<<endl;     
    for(i=0; i<10; i++)          //產生隨機數  
    {  
        cout<<MIN + (int)MAX * rand() / (RAND_MAX + 1)<<"\t";   
    }  
    cout<<endl;  
    return   0;     
}  

二、初始化隨機數發生器srand( )函數的用法

函數名: srand
功 能: 初始化隨機數發生器
用 法: void srand(unsigned int seed);
所在頭文件: stdlib.h
函數說明:
▲srand()用來設置rand()產生隨機數時的隨機數種子。
▲參數seed必須是個整數,通常可以利用time(0)的返回值或NULL來當做seed。
▲如果每次seed都設相同值,rand()所產生的隨機數值每次就會一樣。

三、rand( )和srand( )的聯繫

rand( )和srand( )要一起使用,其中srand( )用來初始化隨機數種子,rand( )用來產生隨機數。
因爲默認情況下隨機數種子爲1,而相同的隨機數種子產生的隨機數是一樣的,失去了隨機性的意義,所以爲使每次得到的隨機數不一樣,用函數srand()初始化隨機數種子。srand()的參數,用time函數值(即當前時間),因爲兩次調用rand()函數的時間通常是不同的,這樣就可以保證隨機性了。

四、產生相同的隨機數的原因

計算機的隨機數都是由僞隨機數,即是由小M多項式序列生成的,其中產生每個小序列都有一個初始值,即隨機種子。(注意: 小M多項式序列的週期是65535,即每次利用一個隨機種子生成的隨機數的週期是65535,當你取得65535個隨機數後它們又重複出現了。)
我們知道rand()函數可以用來產生隨機數,這裏我再囉嗦一遍。計算機中一般不能產生絕對隨機的隨機數。計算機產生隨機數的過程,是根據一個數(我們可以稱它爲種子)爲基準以某個遞推公式推算出來的一系列數,當這系列數很大的時候,就符合正態公佈,從而相當於產生了隨機數,但這不是真正的隨機數,當計算機正常開機後,這個種子的值是確定的,除非你對系統進行了更改。

五、產生一定範圍隨機數的通用算法公式


▲要取得[a,b)的隨機整數,使用(rand() % (b-a))+ a (結果值含a不含b)。
▲要取得[a,b]的隨機整數,使用(rand() % (b-a+1))+ a (結果值含a和b)。
▲要取得(a,b]的隨機整數,使用(rand() % (b-a))+ a + 1 (結果值不含a含b)。
▲即(通用公式:a + rand() % n;取得[a,a+n) 的隨機整數,其中的a是起始值,n是整數的範圍。)
▲要取得[a,b) 的隨機整數,另一種表示:a + (int)(b-a) * rand() / (RAND_MAX + 1)。
▲要取得[a,b] 的隨機整數 另一種表示:a + (int)(b-a) * rand() / (RAND_MAX )。
▲要取得[0,1] 之間的浮點數 ,可以使用rand() / double(RAND_MAX)。

1.產生一個範圍內的隨機數
一般地,我們可用j=1+(int)(n*rand()/(RAND_MAX+1.0))來生成一個0到n之間的隨機數。
若用int x = rand() % 101;來生成 0 到 100 之間的隨機數這種方法是不可取的,比較好的做法是:
j=(int)(100.0*rand()/(RAND_MAX+1.0))
當然,如果是在gcc,vc之外的編譯器,我們也可以使用random(100)。下面的例子都是用了random(n)(VC無法識別random這個函數,VC下我們還是採用 j=(int)(100.0*rand()/(RAND_MAX+1.0)).
2、篩選型隨機數 如希望取0-99的隨機數,但不能是6。
解決方法:
x = random(100);
while (x==6) {
x = random(100);
}
又如希望取0-99的隨機數,但不要5的倍數 解決方法:
x = random(100);
while ((x % 5)==0) {
x = random(100);
}
3、從連續的一段範圍內取隨機數。
如從40--50的範圍內取隨機數。 解決方法: x=random(11)+40
4、從一組亂數中取隨機數。 如:從 67, 87, 34, 78, 12, 5, 9, 108, 999, 378十個數中隨機取數。 解決方法:可以用數組將些十個數存貯,然後把0--9中取出的隨機數作爲序號,實現隨機取數。
a = new Array(67, 87, 34, 78, 12, 5, 9, 108, 999, 378);
j = random(10);
x = a[j];

六、隨機數在遊戲中的應用

有了概率之後,我們只需要在 0~99 之間隨機出數值:

例如 25% ,如果數字在 25~50 之間就表示命中。

裝備強化的成功率,副本里裝備的掉落率,通關獎勵翻牌的掉落率,攻擊暴擊的概率,攻擊MISS的機率,夢幻西遊裏碰到變異寶寶的概率等等都可以這樣實現。



發佈了133 篇原創文章 · 獲贊 4 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章