이것이 내가 정복 이모 테이터 애플릿에서 전투의 승자를 결정하는 데 사용한 것입니다. 이 게임에서는 상황과 유사하게 공격 가치와 방어 가치 만 있습니다. 공격자가 이길 확률은 공격자가 가질 수있는 점수가 높을수록 방어 점수가 더 많을수록 더 많으며, 동일한 값으로 공격이 성공할 확률은 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 - 1L 사이에 있으면 공격자가 이깁니다 . 당첨 조합의 수 는 누적 이항 분포 를 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의 확률을 산출합니다.