小编典典

需要可预测的随机发生器

algorithm

我是一名网络游戏开发商,但我遇到了随机数问题。假设一位玩家有20%的机会用剑获得暴击。这意味着5个匹配中有1个至关重要。问题是我在现实生活中的结果非常糟糕-
有时玩家在5次点击中获得3分,有时15次点击中没有得分。战斗时间很短(3-10次击中),因此获得良好的随机分布非常重要。

目前,我使用PHP mt_rand(),但我们只是将代码移至C ++,因此我想在游戏的新引擎中解决此问题。

我不知道解决方案是某种统一的随机生成器,还是想起以前的随机状态来强制正确分配。


阅读 233

收藏
2020-07-28

共1个答案

小编典典

我同意较早的答案,即小规模游戏的真正随机性是不可取的-对于某些用例而言,这似乎太不公平了。

我用Ruby编写了一个类似于Shuffle Bag的简单实现,并做了一些测试。该实现做到了:

  • 如果看起来仍然很公平,或者我们还没有达到最低限度的下注门槛,那么它会根据正常概率返回合理的命中率。
  • 如果从过去的滚动观察到的概率看起来不公平,则返回“公平化”命中率。

根据边界概率,这被认为是不公平的。例如,对于20%的概率,您可以将10%设置为下限,将40%设置为上限。

利用这些界限,我发现运行10次命中, 真正的伪随机实现产生的结果超出这些界限的时间占14.2%
。大约11%的时间,在10次尝试中得分为0。3.3%的时间中,有10次击中了5个或更多的关键命中。自然地,使用此算法(最小掷骰数为5),很少(0.03%)的“公平”运行超出范围。即使下面的实现不合适(当然,可以做得更聪明),值得注意的是,您的用户通常会感觉到使用真正的伪随机解决方案是不公平的。

这是我FairishBag用Ruby写的肉。完整的实现和快速的蒙特卡洛仿真可在此处找到(要点)

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%,并使短期运行感觉良好。

2020-07-28