如何通过给定的百分比创建概率?

7

我正在尝试为一款游戏创建基于百分比的概率。例如,如果一个物品有45%的暴击几率,那就意味着100次攻击中会有45次暴击。

首先,我尝试使用一个简单的解决方案:

R = new Random();
int C = R.Next(1, 101);
if (C <= ProbabilityPercent) DoSomething()

在进行100次迭代时,如果几率为48%,则会得到40-52个结果。对于49、50、51同样如此。因此,这些“百分比”之间没有区别。
问题是如何设置例如50%的百分比,并通过随机严格获得100中的50个?这对于发现稀有物品的概率以及增加发现物品的机会非常重要。因此,1%的加成将是明智的选择,因为现在还没有达到这一点。
对于我的糟糕英语表示抱歉。

2
你必须明白,“严格50%随机”并不是真正的随机。 - Jon
2
确保你理解随机性。 - Davio
@maelstrom:那么它就不是真正的随机。它是从一个池子里随机选择,而不是真正的随机。就像一副牌的随机,而不是像掷骰子一样的随机。 - LightStriker
@LightStriker 基本上,我需要输入一个概率的 N%,然后它会计算出一个由 100 个 1 和 0 组成的序列,其中有 N 个 "1"。并且将其混合。对吗? - maelstrom
1
另外,需要在哪个窗口中对100个角色进行测量?如果是一个滑动窗口,那么唯一有效的解决方案就是不停地重复相同的100个结果,这样极其非随机。 - Marc Gravell
显示剩余3条评论
4个回答

9

您需要考虑在多次投掷中均匀分布。

不能查看100次投掷,因为迫使其产生恰好45个临界值不会是随机的。通常,这些投掷应该表现出“无记忆性”。例如,如果你投掷一个骰子寻找6,你有1/6的机会。如果您投掷5次,并没有得到6,则下一次投掷得到6的机会并不是1,仍然是1/6。因此,您只能看它在统计上大量事件中实现了您的预期程度...比如说100,000次。

基本上:您当前的代码很好。如果用户知道(因为他们连续击中55次未产生临界值)紧接着的45次必须产生关键一击,那么它就不再是随机的,他们可以操纵系统。

另外;45%的临界打击几率似乎有点高; p


3
@maelstrom 我以为那只是“最大混沌死亡之锤的惊人神圣屠杀”。 - Marc Gravell
非常感谢,我明白了你的意思。也许我对《暗黑破坏神II》的魔法寻找概念过于严肃了。我认为这比我的代码要复杂得多。 - maelstrom
DII MF更加复杂,因为它有递减收益。100%的MF并不能保证只找到蓝色或更好的武器。 :) - Davio
@Davio 如果您能告诉我更多关于这个系统的信息,我将不胜感激。我知道“递减收益”意味着较小值之间的差异比较大,而较大值之间的差异则比较小。但是我该如何实现这样的系统呢? - maelstrom

4
我想创建一个基于百分比的概率用于游戏中。例如,如果一个物品有45%的暴击几率,则意味着100次攻击中会有45次是暴击。

不,这并不正确。你完全误解了概率的概念。你不需要“基于百分比的概率”,而是需要“基于百分比的100个样本的随机分布”。

你需要一个“事件袋”,其中有45个“暴击事件”和55个“非暴击事件”。每次从袋子里取出一个事件后,下一次取出时剩余的事件数会相应减少。

你可以这样建模:

Initialize two integer variables Crytical and NonCrytical so that they sum exactly 100 according to the desired percetnages.

Get a random value from 1 to Crytical+NonCrytical

If the random value is less than the value of Crytical, let you hit be crytical and:

   Crytical = Crytical -1

Else, let your hit be non-crytical

   NonCrytical = NonCrytical-1

End If

Repeat until Crytical+NonCrytical = 0

4

由于我不是C#专家,为了方便起见,我将使用一个C++函数,但仍适用于任何语言。

rand() - 随机数生成器。

//33.34%
double probability = 0.3334;

//divide to get a number between 0 and 1
double result = rand() / RAND_MAX;
if(result < probability)
   //do something

我曾使用这种方法创建非常大的渗透网格,对于精确值而言,它的效果非常好。

0

问题是,使用Random类时,您可能只想初始化一次。

这是因为Random使用系统时间作为生成随机数的种子。如果您的循环非常快,可能会发生多个Random实例使用相同的种子从而生成相同的数字。

如果您怀疑出现这种情况,请检查生成的数字。

除此之外,随机性固有的特点是它不会给您精确的结果。这意味着即使是50/50的几率,也可能发生100个“正面”或“反面”的序列中全部都是“正面”。

您唯一能做的就是创建一个Random实例并接受结果;否则,您不应该使用Random。


好的,他说“迭代”,所以我认为他可能使用了循环,所以我想警告他在循环中初始化 Random 可能会产生的副作用。 - Davio
我为了测试目的使用了一个循环。并且在循环之前初始化了随机数。 - maelstrom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接