Ini adalah apa yang saya gunakan untuk menentukan pemenang pertempuran di applet Lords of Conquest Imitator saya. Dalam game ini, mirip dengan situasi Anda, hanya ada nilai serangan dan nilai pertahanan. Probabilitas bahwa penyerang menang adalah lebih besar semakin banyak poin yang dimiliki penyerang, dan semakin sedikit poin yang dimiliki oleh penyerang, dengan nilai yang sama dievaluasi dengan peluang 50% dari serangan yang berhasil.
Algoritma
Balikkan koin acak.
1a. Kepala: pertahanan kehilangan satu poin.
1b. Ekor: kepala kehilangan satu poin.
Jika pertahanan dan penyerang masih memiliki poin, kembali ke langkah 1.
Siapa pun yang turun ke 0 poin kalah dalam pertempuran.
3a. Penyerang ke 0: Serangan gagal.
3b. Pertahanan ke 0: Serangan berhasil.
Saya menulisnya di Jawa, tetapi harus mudah diterjemahkan ke bahasa lain.
Random rnd = new Random();
while (att > 0 && def > 0)
{
if (rnd.nextDouble() < 0.5)
def--;
else
att--;
}
boolean attackSucceeds = att > 0;
Sebuah contoh
Misalnya, katakanlah att = 2 dan def = 2, hanya untuk memastikan bahwa probabilitasnya adalah 50%.
Pertempuran akan ditentukan dalam jumlah maksimum n = att + def - 1
koin membalik, atau 3 dalam contoh ini (pada dasarnya ini adalah yang terbaik dari 3 di sini). Ada 2 n kemungkinan kombinasi membalik koin. Di sini, "W" berarti penyerang memenangkan flip koin, dan "L" berarti penyerang kehilangan flip koin.
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
Penyerang menang di 4/8, atau 50% dari kasus.
Matematika
Probabilitas matematika yang timbul dari algoritma sederhana ini lebih rumit daripada algoritma itu sendiri.
Jumlah kombinasi di mana tepatnya x Ls diberikan oleh fungsi kombinasi:
C(n, x) = n! / (x! * (n - x)!)
Penyerang menang ketika ada di antara 0
dan att - 1
Ls. Jumlah kombinasi pemenang sama dengan jumlah kombinasi dari 0
through att - 1
, distribusi binomial kumulatif:
(att - 1)
w = Σ C(n, x)
x = 0
Probabilitas penyerang menang adalah w dibagi 2 n , probabilitas binomial kumulatif:
p = w / 2^n
Berikut adalah kode di Jawa untuk menghitung probabilitas ini untuk nilai arbitrer att
dan 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;
}
Kode pengujian:
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));
}
Keluaran:
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
Pengamatan
Peluangnya adalah 0.0
jika penyerang memiliki 0
poin, 1.0
jika penyerang memiliki poin tetapi pertahanan memiliki 0
poin, 0.5
jika poinnya sama, kurang dari 0.5
jika penyerang memiliki lebih sedikit poin daripada pertahanan, dan lebih besar dari 0.5
jika penyerang memiliki lebih banyak poin daripada pertahanan .
Mengambil att = 50
dan def = 80
, saya perlu beralih ke BigDecimal
s untuk menghindari overflow, tapi saya mendapatkan probabilitas sekitar 0,0040.
Anda dapat membuat probabilitas lebih dekat ke 0,5 dengan mengubah att
nilai menjadi rata-rata att
dan def
nilai. Att = 50, Def = 80 menjadi (65, 80), yang menghasilkan probabilitas 0,1056.