이것이 내가 정복 이모 테이터 애플릿에서 전투의 승자를 결정하는 데 사용한 것입니다. 이 게임에서는 상황과 유사하게 공격 가치와 방어 가치 만 있습니다. 공격자가 이길 확률은 공격자가 가질 수있는 점수가 높을수록 방어 점수가 더 많을수록 더 많으며, 동일한 값으로 공격이 성공할 확률은 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;
예
예를 들어, 확률이 50 %인지 확인하기 위해 att = 2 및 def = 2라고 가정하겠습니다.
전투는 최대 n = att + def - 1
동전 뒤집기 또는이 예에서는 3 으로 결정됩니다 (기본적으로 최고 3입니다). 2 개의 가능한 코인 플립 조합이 있습니다. 여기서 "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 L이있는 조합의 수는 조합 함수에 의해 제공됩니다.
C(n, x) = n! / (x! * (n - x)!)
L 0
과 att - 1
L 사이에 있으면 공격자가 이깁니다 . 당첨 조합의 수 는 누적 이항 분포 를 0
통한 조합의 합과 att - 1
같습니다.
(att - 1)
w = Σ C(n, x)
x = 0
침입자의 확률 승리는 승 (2)에 의해 분할 된 N , 누적 이항 확률 :
p = w / 2^n
여기서, 임의의 확률이 계산에서 자바 코드 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
피하기 오버 플로우의,하지만 난 0.0040 정도의 확률을 얻을.
att
값을 att
및 def
값 의 평균으로 변경하여 확률을 0.5에 가깝게 만들 수 있습니다 . Att = 50, Def = 80은 (65, 80)이되어 0.1056의 확률을 산출합니다.