นี่คือสิ่งที่ฉันใช้เพื่อกำหนดผู้ชนะการต่อสู้ในแอปเพล็ต Lords of Conquest Imitator ของฉัน ในเกมนี้คล้ายกับสถานการณ์ของคุณมีเพียงค่าการโจมตีและค่าการป้องกัน ความน่าจะเป็นที่ผู้โจมตีชนะจะยิ่งได้คะแนนมากขึ้นเท่าที่ผู้โจมตีจะได้รับและยิ่งมีคะแนนน้อยลงเท่าใดนักที่มีค่าเท่ากันประเมินว่ามีโอกาส 50% ที่การโจมตีสำเร็จ
ขั้นตอนวิธี
พลิกเหรียญสุ่ม
1a หัว: การป้องกันสูญเสียจุด
1b ก้อย: หัวเสียคะแนน
หากทั้งการป้องกันและการโจมตียังคงมีคะแนนให้กลับไปที่ขั้นตอนที่ 1
ใครก็ตามที่ลงไป 0 คะแนนแพ้การต่อสู้
3a ผู้โจมตีถึง 0: การโจมตีล้มเหลว
3b ป้องกันลงถึง 0: การโจมตีสำเร็จ
ฉันเขียนเป็นภาษาจาวา แต่ควรแปลเป็นภาษาอื่นได้ง่าย
Random rnd = new Random();
while (att > 0 && def > 0)
{
if (rnd.nextDouble() < 0.5)
def--;
else
att--;
}
boolean attackSucceeds = att > 0;
ตัวอย่าง
ตัวอย่างเช่นสมมุติว่า att = 2 และ def = 2 เพียงเพื่อให้แน่ใจว่าความน่าจะเป็นคือ 50%
การต่อสู้จะตัดสินด้วยการn = att + def - 1
พลิกเหรียญสูงสุดหรือ 3 ในตัวอย่างนี้ (โดยพื้นฐานแล้วมันจะดีที่สุด 3 อันดับ) มี 2 nผสมเป็นไปได้ของเหรียญพลิก ที่นี่ "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แอลเอสจะได้รับจากการทำงานรวมกัน:
C(n, x) = n! / (x! * (n - x)!)
ผู้โจมตีชนะเมื่ออยู่ระหว่าง0
ถึงatt - 1
Ls จำนวนชุดค่าผสมที่ชนะเท่ากับผลรวมของชุดค่าผสมจาก0
ถึงatt - 1
การแจกแจงแบบทวินามสะสม:
(att - 1)
w = Σ C(n, x)
x = 0
น่าจะเป็นของการโจมตีชนะคือWโดยแบ่งออกเป็น 2 n , ความน่าจะเป็นทวินามสะสม:
p = w / 2^n
นี่คือรหัสใน Java เพื่อคำนวณความน่าจะเป็นนี้โดยพลการ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
s เพื่อหลีกเลี่ยงการล้น แต่ฉันได้รับความน่าจะเป็นประมาณ 0.0040
คุณสามารถทำให้ความน่าจะเป็นใกล้เคียง 0.5 โดยการเปลี่ยนatt
ค่าให้เป็นค่าเฉลี่ยของatt
และdef
ค่า Att = 50, Def = 80 กลายเป็น (65, 80) ซึ่งให้ความน่าจะเป็นที่ 0.1056