哪種隨機數生成演算法最適合遊戲使用?

1. 可序列化, 且序列化的數據很小, 最好是4個位元組, 最大不超過8個位元組;

2. 在給定初始狀態下具有可預測的變化序列, 周期儘可能大;

3. 儘可能的快速且高質量.

PS1: 最開始我用 .NET 的 Random, 但是它使用了 56 長度的 int 數組, 並且全部都會序列化, 而且不能讀寫 seed. 如果您知道它的原理的話請告訴我.

PS2: 答案可能是某種線性同餘法, 如果是的話請具體告知哪個方法什麼參數.


條件 1 和 2 是明顯對立的條件。對於一個有n位狀態的偽隨機數生成器(PRNG),理論上最大的周期為2^n。而 PRNG 都是固定序列的。

條件 3 中的「快速」和「高質量」也是對立的。

遊戲對於偽隨機數也不同的需求。例如用來做粒子特效的話,性能比質量重要;用來洗牌的話,要避免猜到對方的牌,可能需要更高品質及安全性。

遊戲中常用到的 ,生成 32 位隨機數的 PRNG 有:

  1. Linear congruential generator 通常用32位的狀態。常用的 Numerical Recipes 的版本(a = 1664525, c = 1013904223, m = 2^{32})周期為2^{32}approx 4.3 	imes 10^9,非常高效。

  2. Xorshift 128位狀態,不用加法和乘法,具2^{128}-1 approx 3.4 	imes 10^{38}的周期。(在以前的機器上有優勢,但現在乘法加法很快)

  3. Mersenne Twister 通常用 19937 位狀態(一般儲存成19968位),具2^{19937}-1 approx 4.3 	imes 10^{6001}的周期。

最後,以撲克牌為例,52 張牌有 52! approx 8 	imes 10^{67} 種排列,需要至少 414 位才能表示所有排列方式。上述哪個 PRNG 比較合適?


對天朝遊戲來說,概率涉及到抽卡,抽卡感受涉及到充值,充值涉及到開發團隊的生死存亡。不可不慎也。

樓主的問題還是很贊的,大規模調用下的隨機抽取功能,往往結果和想要的不一致。樓主是想從隨機數發生的角度解決問題,下面談談看法。

先拋結論:

對遊戲來說,隨機數發生器並不重要,重要的是你最後實現的,到底是統計意義上的概率,還是分布意義上的概率。

再上參考資料:

抽卡藝術:深度分析遊戲中隨機概率 - GameRes遊資網

無論用哪種發生器,都很難直接做到下圖這種穩定理想的分布性。所以解決方法是,一定要保存目前抽取的狀態。對於一張卡來說,就必須用到一個整數。

這個整數根據你的遊戲規則,設定一個隨機值,比如RandInt(0,100),百分之一的概率,比如得到了23,那麼代表第23次時,會抽到這張卡。這麼說一下應該能看懂,具體的需要再研究圖前面的鏈接了。

和樓主的問題略有點脫節,但是可能會有啟發吧。歡迎討論。


我突然想到爐石的橙卡傳送門


反正我們只用兩種,Mersenne Twister和taus88。前一種是c++11標準隨機數演算法,但是每次隨機數計算for循環里要執行600+次(32位,64位次數減半)有點受不了,所以頻繁的隨機數還是用了taus88演算法


作業自己做啊。。


感覺 各個標準庫里自帶的 線性同餘函數 就足夠了。

如果一定覺得2^32的周期太短,或者可預測性太強,我的做法是:

空閑時,n=邊上某個與外部環境關係較緊密的變數的值 mod 10,空執行n次隨機函數(跳過n個),

或者 每次取隨機數時,都這麼做(效率略低)。

不過,都沒能嚴格量化、證明:這2種做法是不是真的加強了隨機性


難道不是

srand((unsigned)time(null)

x =rand()


推薦閱讀:

Weighted linear matroid parity問題
從兩道亦可賽艇的演算法題看字典的神奇作用
BAT機器學習面試1000題系列(281-285)
萌新刷題(九)二叉查找樹迭代器

TAG:遊戲 | 演算法 | 隨機數 | 遊戲編程 | 隨機數發生器 |