問題描述
我是一名網絡游戲開發者,我遇到了隨機數問題.假設一個玩家有 20% 的幾率用他的劍造成致命一擊.這意味著,五分之一的命中應該是關鍵的.問題是我在現實生活中得到了非常糟糕的結果—有時玩家在 5 次點擊中獲得 3 次暴擊,有時在 15 次點擊中沒有.戰斗時間很短(3-10 次點擊),因此獲得良好的隨機分布很重要.
I'm a web-game developer and I got a problem with random numbers. Let's say that a player has 20% chance to get a critical hit with his sword. That means, 1 out of 5 hits should be critical. The problem is I got very bad real life results — sometimes players get 3 crits in 5 hits, sometimes none in 15 hits. Battles are rather short (3-10 hits) so it's important to get good random distribution.
目前我使用 PHP mt_rand()
,但我們只是將代碼移至 C++,所以我想在我們游戲的新引擎中解決這個問題.
Currently I use PHP mt_rand()
, but we are just moving our code to C++, so I want to solve this problem in our game's new engine.
我不知道該解決方案是否是某種均勻隨機生成器,或者可能是記住以前的隨機狀態以強制正確分布.
I don't know if the solution is some uniform random generator, or maybe to remember previous random states to force proper distribution.
推薦答案
我同意之前的回答,即某些游戲的小規模運行中的真正隨機性是不可取的——這對于某些用例來說似乎太不公平了.
I agree with the earlier answers that real randomness in small runs of some games is undesirable -- it does seem too unfair for some use cases.
我用 Ruby 編寫了一個類似 Shuffle Bag 的簡單實現,并做了一些測試.實現是這樣的:
I wrote a simple Shuffle Bag like implementation in Ruby and did some testing. The implementation did this:
- 如果它看起來仍然公平,或者我們還沒有達到最小擲骰子的閾值,它會根據正態概率返回一個公平的命中.
- 如果從過去的滾動中觀察到的概率使它看起來不公平,它會返回一個公平化"的命中.
根據邊界概率,它被認為是不公平的.例如,對于 20% 的概率,您可以將 10% 設置為下限,將 40% 設置為上限.
It is deemed unfair based on boundary probabilities. For instance, for a probability of 20%, you could set 10% as a lower bound and 40% as an upper bound.
使用這些界限,我發現運行 10 次命中后,14.2% 的時間真正的偽隨機實現產生的結果超出這些界限.大約 11% 的時間里,在 10 次嘗試中得分為 0.在 3.3% 的時間里,10 次中的 5 次或更多次重擊命中.自然,使用此算法(最小擲骰數為 5),Fairish"運行的數量要少得多(0.03%)..即使下面的實現不合適(當然可以做更聰明的事情),值得注意的是,您的用戶通常會覺得使用真正的偽隨機解決方案是不公平的.
Using those bounds, I found that with runs of 10 hits, 14.2% of the time the true pseudorandom implementation produced results that were out of those bounds. About 11% of the time, 0 critical hits were scored in 10 tries. 3.3% of the time, 5 or more critical hits were landed out of 10. Naturally, using this algorithm (with a minimum roll count of 5), a much smaller amount (0.03%) of the "Fairish" runs were out of bounds. Even if the below implementation is unsuitable (more clever things can be done, certainly), it is worth noting that noticably often your users will feel that it's unfair with a real pseudorandom solution.
這是我用 Ruby 編寫的 FairishBag
的主要內容.整個實現和快速蒙特卡羅模擬 可在此處 (gist) 獲得.
Here is the meat of my FairishBag
written in Ruby. The whole implementation and quick Monte Carlo simulation is available here (gist).
def fire!
hit = if @rolls >= @min_rolls && observed_probability > @unfair_high
false
elsif @rolls >= @min_rolls && observed_probability < @unfair_low
true
else
rand <= @probability
end
@hits += 1 if hit
@rolls += 1
return hit
end
def observed_probability
@hits.to_f / @rolls
end
更新:使用此方法確實會增加獲得重擊的總體概率,使用上述界限可提高到約 22%.您可以通過將其真實"概率設置得低一點來抵消這一點.17.5% 的概率與公平修改產生約 20% 的長期觀察概率,并保持短期運行感覺公平.
Update: Using this method does increase the overall probability of getting a critical hit, to about 22% using the bounds above. You can offset this by setting its "real" probability a little bit lower. A probability of 17.5% with the fairish modification yields an observed long term probability of about 20%, and keeps the short term runs feeling fair.
這篇關于需要可預測的隨機生成器的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!