需要可预测的随机生成器

Need for predictable random generator(需要可预测的随机生成器)
本文介绍了需要可预测的随机生成器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我是一名网络游戏开发者,我遇到了随机数问题.假设一个玩家有 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.

这篇关于需要可预测的随机生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Returning a pointer of a local variable C++(返回局部变量 C++ 的指针)
Inline function linkage(内联函数联动)
Which is more efficient: Return a value vs. Pass by reference?(哪个更有效:返回值与通过引用传递?)
Why is std::function not equality comparable?(为什么 std::function 不具有可比性?)
C++ overload resolution(C++ 重载解析)
When to Overload the Comma Operator?(什么时候重载逗号运算符?)