Đây là những gì tôi đã sử dụng để xác định người chiến thắng trong một trận chiến trong applet Lords of Conquest Imitator của tôi. Trong trò chơi này, tương tự như tình huống của bạn, chỉ có giá trị tấn công và giá trị phòng thủ. Xác suất mà kẻ tấn công giành được càng nhiều thì kẻ tấn công càng có nhiều điểm và phòng thủ càng có nhiều điểm, với các giá trị bằng nhau đánh giá khả năng thành công của cuộc tấn công là 50%.
Thuật toán
Lật một đồng xu ngẫu nhiên.
1a. Thủ trưởng: phòng thủ mất một điểm.
1b. Đuôi: đầu mất một điểm.
Nếu cả phòng thủ và kẻ tấn công vẫn có điểm, hãy quay lại bước 1.
Ai bị hạ 0 điểm thì thua trận.
3a. Kẻ tấn công xuống 0: Tấn công thất bại.
3b. Phòng thủ xuống 0: Tấn công thành công.
Tôi đã viết nó bằng Java, nhưng nó có thể dễ dàng dịch sang các ngôn ngữ khác.
Random rnd = new Random();
while (att > 0 && def > 0)
{
if (rnd.nextDouble() < 0.5)
def--;
else
att--;
}
boolean attackSucceeds = att > 0;
Một ví dụ
Ví dụ: giả sử att = 2 và def = 2, chỉ để đảm bảo rằng xác suất là 50%.
Trận chiến sẽ được quyết định trong tối đa số n = att + def - 1lần lật đồng xu, hoặc 3 trong ví dụ này (về cơ bản là tốt nhất trong số 3 ở đây). Có 2 n kết hợp có thể của lật đồng xu. Ở đây, "W" có nghĩa là kẻ tấn công đã giành được lật đồng xu và "L" có nghĩa là kẻ tấn công bị mất đồng xu lật.
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
Kẻ tấn công thắng trong 4/8, hoặc 50% các trường hợp.
Toán
Các xác suất toán học phát sinh từ thuật toán đơn giản này phức tạp hơn chính thuật toán.
Số lượng kết hợp trong đó có chính xác x Ls được đưa ra bởi hàm kết hợp:
C(n, x) = n! / (x! * (n - x)!)
Kẻ tấn công chiến thắng khi có giữa 0và att - 1Ls. Số lượng kết hợp chiến thắng bằng tổng số kết hợp từ 0xuyên qua att - 1, phân phối nhị thức tích lũy:
(att - 1)
w = Σ C(n, x)
x = 0
Xác suất của những kẻ tấn công chiến thắng được w chia cho 2 n , một xác suất nhị thức tích lũy:
p = w / 2^n
Đây là mã trong Java để tính xác suất này cho các giá trị attvà defgiá trị tùy ý :
/**
* 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;
}
Mã kiểm tra:
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));
}
Đầu ra:
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
Quan sát
Xác suất là 0.0nếu kẻ tấn công có 0điểm, 1.0nếu kẻ tấn công có điểm nhưng phòng thủ có 0điểm, 0.5nếu điểm bằng nhau, ít hơn 0.5nếu kẻ tấn công có ít điểm hơn phòng thủ và lớn hơn 0.5nếu kẻ tấn công có nhiều điểm hơn phòng thủ .
Lấy att = 50và def = 80, tôi cần chuyển sang BigDecimals để tránh tràn, nhưng tôi có xác suất khoảng 0,0040.
Bạn có thể làm cho xác suất gần bằng 0,5 bằng cách thay đổi attgiá trị thành trung bình của các giá trị attvà def. Att = 50, Def = 80 trở thành (65, 80), mang lại xác suất 0,1056.