这就是我用来确定“征服之王”模仿者小程序中战斗胜利者的方法。在此游戏中,与您的情况类似,只有攻击值和防御值。攻击者获胜的概率越大,攻击者拥有的得分就越多,而防御者拥有的得分就越少,而相等的值估计攻击成功的机会为50%。
算法
翻转随机硬币。
1a。负责人:防守失分。
1b。尾巴:头丢了一点。
如果防御者和攻击者双方仍然有分数,请返回步骤1。
下降到0分的人将输掉这场战斗。
3a。攻击者降至0:攻击失败。
3b。防御降至0:攻击成功。
我用Java编写了它,但是它应该可以轻松翻译成其他语言。
Random rnd = new Random();
while (att > 0 && def > 0)
{
if (rnd.nextDouble() < 0.5)
def--;
else
att--;
}
boolean attackSucceeds = att > 0;
一个例子
例如,假设att = 2和def = 2,只是为了确保概率为50%。
战斗将以最多n = att + def - 1
掷硬币而决定,在此示例中为3(在此基本上是3的最佳成绩)。掷硬币有2 n种可能的组合。在此,“ W”表示攻击者赢得了掷硬币,而“ L”表示攻击者失去了掷硬币。
L,L,L - Attacker loses
L,L,W - Attacker loses
L,W,L - Attacker loses
L,W,W - Attacker wins
W,L,L - Attacker loses
W,L,W - Attacker wins
W,W,L - Attacker wins
W,W,W - Attacker wins
攻击者在4/8或50%的情况下获胜。
数学
由这种简单算法产生的数学概率比算法本身更复杂。
确切有x Ls的组合数由组合函数给出:
C(n, x) = n! / (x! * (n - x)!)
当介于0
和att - 1
Ls 之间时,攻击者获胜。获胜组合的数量等于从0
到的组合总和att - 1
,即累积的二项式分布:
(att - 1)
w = Σ C(n, x)
x = 0
攻击者获胜的概率用w除以2 n,即累积的二项式概率:
p = w / 2^n
这是Java中用于计算任意值att
和def
值的概率的代码:
/**
* Returns the probability of the attacker winning.
* @param att The attacker's points.
* @param def The defense's points.
* @return The probability of the attacker winning, between 0.0 and 1.0.
*/
public static double probWin(int att, int def)
{
long w = 0;
int n = att + def - 1;
if (n < 0)
return Double.NaN;
for (int i = 0; i < att; i++)
w += combination(n, i);
return (double) w / (1 << n);
}
/**
* Computes C(n, k) = n! / (k! * (n - k)!)
* @param n The number of possibilities.
* @param k The number of choices.
* @return The combination.
*/
public static long combination(int n, int k)
{
long c = 1;
for (long i = n; i > n - k; i--)
c *= i;
for (long i = 2; i <= k; i++)
c /= i;
return c;
}
测试代码:
public static void main(String[] args)
{
for (int n = 0; n < 10; n++)
for (int k = 0; k <= n; k++)
System.out.println("C(" + n + ", " + k + ") = " + combination(n, k));
for (int att = 0; att < 5; att++)
for (int def = 0; def < 10; def++)
System.out.println("att: " + att + ", def: " + def + "; prob: " + probWin(att, def));
}
输出:
att: 0, def: 0; prob: NaN
att: 0, def: 1; prob: 0.0
att: 0, def: 2; prob: 0.0
att: 0, def: 3; prob: 0.0
att: 0, def: 4; prob: 0.0
att: 1, def: 0; prob: 1.0
att: 1, def: 1; prob: 0.5
att: 1, def: 2; prob: 0.25
att: 1, def: 3; prob: 0.125
att: 1, def: 4; prob: 0.0625
att: 1, def: 5; prob: 0.03125
att: 2, def: 0; prob: 1.0
att: 2, def: 1; prob: 0.75
att: 2, def: 2; prob: 0.5
att: 2, def: 3; prob: 0.3125
att: 2, def: 4; prob: 0.1875
att: 2, def: 5; prob: 0.109375
att: 2, def: 6; prob: 0.0625
att: 3, def: 0; prob: 1.0
att: 3, def: 1; prob: 0.875
att: 3, def: 2; prob: 0.6875
att: 3, def: 3; prob: 0.5
att: 3, def: 4; prob: 0.34375
att: 3, def: 5; prob: 0.2265625
att: 3, def: 6; prob: 0.14453125
att: 3, def: 7; prob: 0.08984375
att: 4, def: 0; prob: 1.0
att: 4, def: 1; prob: 0.9375
att: 4, def: 2; prob: 0.8125
att: 4, def: 3; prob: 0.65625
att: 4, def: 4; prob: 0.5
att: 4, def: 5; prob: 0.36328125
att: 4, def: 6; prob: 0.25390625
att: 4, def: 7; prob: 0.171875
att: 4, def: 8; prob: 0.11328125
观察结果
概率是:0.0
如果攻击者拥有0
分数,1.0
如果攻击者具有分数但防御者具有0
分数,0.5
如果分数相等,则小于(0.5
如果攻击者具有的分数小于防御者的分数)则大于(0.5
如果攻击者的分数大于防御者的分数) 。
采用att = 50
和def = 80
,我需要切换到BigDecimal
s以避免溢出,但是我得到的概率约为0.0040。
通过将att
值更改为att
和def
值的平均值,可以使概率接近0.5 。Att = 50,Def = 80变为(65,80),得出的概率为0.1056。