用蒙特卡洛方法計算小遊戲獲勝概率(Python實現)
阿新 • • 發佈:2018-12-20
遊戲描述:
有兩人X和Y,遊戲之前兩人分別擁有籌碼x個和y個,兩人開始進行每人獲勝概率都是50%的比拼,如果X贏了,並且之前x>=y,那麼遊戲結束,X獲勝;如果X贏了,但是之前x<y,則X的籌碼翻倍,變成2x,Y的籌碼變成y-x,遊戲繼續; 問:當x,y取不同值時,X的獲勝概率分別是多少。
什麼是蒙特卡洛方法
- 蒙特卡羅(Monte Carlo)方法:用統計結果去計算頻率,從而得到真實值的近似值。
- 一個簡單例子: 比如你有一枚硬幣,想計算扔硬幣正面朝上的概率,那你可以仍很多次(例如100000次),記錄正面朝上的次數(比如50012次),最終可得到正面朝上概率=正面朝上次數/總次數=50012/100000=50.012%。
- 扔100000次硬幣想想就很痛苦,不過沒關係,我們現在可以利用計算機幫助我們模擬大量的隨機實驗
解題思路:
- 首先構造一個雙方獲勝概率分別是50%的比拼: X和Y分別取0到1之間的一個隨機數,若x_score>y_score,則X獲勝,若y_score>x_score,則Y獲勝,那麼這個比拼中X和Y的獲勝概率都是50%;
- 對某個特定的x和y值,模擬一次遊戲,待遊戲結束,如果X獲勝,則記錄1,如果Y獲勝,則記錄0;
- 對某個特定的x和y值,模擬100000次遊戲,記錄X獲勝次數(1的個數),計算X獲勝概率。
- 對於不同的x和y值,進行實驗,得到不同x和y值時X的獲勝概率。
- 總結規律,X的獲勝概率和初始值x,y的關係是什麼?
用python實現
import numpy as np import pandas as pd # 模擬一次遊戲 def match(init_x, init_y): x = init_x y = init_y x_result = None while x_result is None: if x == 0: x_result = 0 elif y == 0: x_result = 1 else: x_score, y_score = np.random.rand(2) # X和Y分別得到一個0到1的隨機數 if x >= y: if x_score > y_score: x_result = 1 elif x_score < y_score: x = x - y y = y + y else: continue else: if x_score < y_score: x_result = 0 elif x_score > y_score: y = y - x x = x + x else: continue return x_result # 模擬n次遊戲,計算獲勝概率 def simulation_test(x, y, n): test_results = [] for i in range(n): r = match(x, y) test_results.append(r) p = np.mean(test_results)*100 return p # x從1到10取值,y從1到10取值,對於不同的(x,y)數值對,計算X獲勝概率 def main(): results = [] for x in range(1,11): for y in range(1,11): x_win_rate = simulation_test(x, y, 100000) d = {'x': x, 'y': y, 'x_win_rate': x_win_rate} results.append(d) df = pd.DataFrame(results, columns=['x','y','x_win_rate']) pd.set_option('display.max_rows', None) print(df) if __name__ == "__main__": main()
執行結果:
x | y | x_win_rate | |
---|---|---|---|
0 | 1 | 1 | 49.919 |
1 | 1 | 2 | 33.460 |
2 | 1 | 3 | 25.110 |
3 | 1 | 4 | 19.996 |
4 | 1 | 5 | 16.797 |
5 | 1 | 6 | 14.293 |
6 | 1 | 7 | 12.578 |
7 | 1 | 8 | 11.211 |
8 | 1 | 9 | 10.010 |
9 | 1 | 10 | 9.026 |
10 | 2 | 1 | 66.556 |
11 | 2 | 2 | 50.027 |
12 | 2 | 3 | 40.093 |
13 | 2 | 4 | 33.200 |
14 | 2 | 5 | 28.639 |
15 | 2 | 6 | 24.925 |
16 | 2 | 7 | 22.363 |
17 | 2 | 8 | 20.185 |
18 | 2 | 9 | 18.279 |
19 | 2 | 10 | 16.671 |
20 | 3 | 1 | 75.035 |
21 | 3 | 2 | 60.017 |
22 | 3 | 3 | 49.626 |
23 | 3 | 4 | 42.879 |
24 | 3 | 5 | 37.835 |
25 | 3 | 6 | 33.289 |
26 | 3 | 7 | 30.064 |
27 | 3 | 8 | 27.138 |
28 | 3 | 9 | 24.967 |
29 | 3 | 10 | 23.038 |
30 | 4 | 1 | 79.894 |
31 | 4 | 2 | 66.645 |
32 | 4 | 3 | 57.186 |
33 | 4 | 4 | 50.064 |
34 | 4 | 5 | 44.298 |
35 | 4 | 6 | 39.963 |
36 | 4 | 7 | 36.201 |
37 | 4 | 8 | 33.507 |
38 | 4 | 9 | 30.812 |
39 | 4 | 10 | 28.466 |
40 | 5 | 1 | 83.283 |
41 | 5 | 2 | 71.550 |
42 | 5 | 3 | 62.713 |
43 | 5 | 4 | 55.711 |
44 | 5 | 5 | 49.919 |
45 | 5 | 6 | 45.489 |
46 | 5 | 7 | 41.779 |
47 | 5 | 8 | 38.394 |
48 | 5 | 9 | 35.679 |
49 | 5 | 10 | 33.524 |
50 | 6 | 1 | 85.775 |
51 | 6 | 2 | 74.984 |
52 | 6 | 3 | 66.658 |
53 | 6 | 4 | 60.043 |
54 | 6 | 5 | 54.330 |
55 | 6 | 6 | 49.834 |
56 | 6 | 7 | 46.212 |
57 | 6 | 8 | 42.831 |
58 | 6 | 9 | 40.023 |
59 | 6 | 10 | 37.740 |
60 | 7 | 1 | 87.472 |
61 | 7 | 2 | 77.576 |
62 | 7 | 3 | 69.897 |
63 | 7 | 4 | 63.773 |
64 | 7 | 5 | 58.175 |
65 | 7 | 6 | 53.834 |
66 | 7 | 7 | 50.219 |
67 | 7 | 8 | 46.754 |
68 | 7 | 9 | 43.511 |
69 | 7 | 10 | 41.235 |
70 | 8 | 1 | 88.769 |
71 | 8 | 2 | 79.780 |
72 | 8 | 3 | 72.694 |
73 | 8 | 4 | 66.335 |
74 | 8 | 5 | 61.715 |
75 | 8 | 6 | 57.178 |
76 | 8 | 7 | 53.487 |
77 | 8 | 8 | 50.012 |
78 | 8 | 9 | 46.984 |
79 | 8 | 10 | 44.524 |
80 | 9 | 1 | 89.938 |
81 | 9 | 2 | 81.958 |
82 | 9 | 3 | 75.107 |
83 | 9 | 4 | 69.155 |
84 | 9 | 5 | 64.436 |
85 | 9 | 6 | 59.974 |
86 | 9 | 7 | 55.978 |
87 | 9 | 8 | 52.774 |
88 | 9 | 9 | 50.242 |
89 | 9 | 10 | 47.185 |
90 | 10 | 1 | 90.896 |
91 | 10 | 2 | 83.411 |
92 | 10 | 3 | 76.798 |
93 | 10 | 4 | 71.518 |
94 | 10 | 5 | 66.650 |
95 | 10 | 6 | 62.489 |
96 | 10 | 7 | 58.818 |
97 | 10 | 8 | 55.756 |
98 | 10 | 9 | 52.601 |
99 | 10 | 10 | 50.057 |
大膽假設: P = x/(x+y)?
驗證: x=1, y=2, p=1/3=33.3%,實驗結果33.460%, x=1, y=3, p=1/4=25.0%,實驗結果25.110%, x=1, y=6, p=1/7=14.3%,實驗結果14.293%, x=1, y=8, p=1/9=11.1%,實驗結果11.211%, ......
通過實驗資料驗證,實驗結果確實接近x/(x+y)。
總結規律,找到公式:
X獲勝概率P=x/(x+y),也就是說獲勝概率等於初始籌碼佔總籌碼的比例。