Đâ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 - 1
lầ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 0
và att - 1
Ls. Số lượng kết hợp chiến thắng bằng tổng số kết hợp từ 0
xuyê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ị att
và def
giá 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.0
nếu kẻ tấn công có 0
điểm, 1.0
nếu kẻ tấn công có điểm nhưng phòng thủ có 0
điểm, 0.5
nếu điểm bằng nhau, ít hơn 0.5
nếu kẻ tấn công có ít điểm hơn phòng thủ và lớn hơn 0.5
nếu kẻ tấn công có nhiều điểm hơn phòng thủ .
Lấy att = 50
và def = 80
, tôi cần chuyển sang BigDecimal
s để 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 att
giá trị thành trung bình của các giá trị att
và def
. Att = 50, Def = 80 trở thành (65, 80), mang lại xác suất 0,1056.