哪種隨機數生成演算法最適合遊戲使用?
1. 可序列化, 且序列化的數據很小, 最好是4個位元組, 最大不超過8個位元組;
2. 在給定初始狀態下具有可預測的變化序列, 周期儘可能大;3. 儘可能的快速且高質量.PS1: 最開始我用 .NET 的 Random, 但是它使用了 56 長度的 int 數組, 並且全部都會序列化, 而且不能讀寫 seed. 如果您知道它的原理的話請告訴我.
PS2: 答案可能是某種線性同餘法, 如果是的話請具體告知哪個方法什麼參數.
條件 1 和 2 是明顯對立的條件。對於一個有位狀態的偽隨機數生成器(PRNG),理論上最大的周期為。而 PRNG 都是固定序列的。
條件 3 中的「快速」和「高質量」也是對立的。
遊戲對於偽隨機數也不同的需求。例如用來做粒子特效的話,性能比質量重要;用來洗牌的話,要避免猜到對方的牌,可能需要更高品質及安全性。
遊戲中常用到的 ,生成 32 位隨機數的 PRNG 有:- Linear congruential generator 通常用32位的狀態。常用的 Numerical Recipes 的版本()周期為,非常高效。
- Xorshift 128位狀態,不用加法和乘法,具的周期。(在以前的機器上有優勢,但現在乘法加法很快)
- Mersenne Twister 通常用 19937 位狀態(一般儲存成19968位),具的周期。
最後,以撲克牌為例,52 張牌有 種排列,需要至少 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)
※萌新刷題(九)二叉查找樹迭代器