隨機機制的探索(RandomPicker中文文件)
RandomPicker?? 最初的靈感來來自音樂隨機播放:
權重++
切歌模式
最近在研究遊戲機制,發現隨機在遊戲領域有著廣闊的空間。隨機和博弈往往聯絡在一起,而博弈的英文即‘game’,非常有趣的一個詞。
暴擊機制與翻牌隨機
在這裡,推薦一篇非常不錯的文章: 隨機機制在遊戲中的應用與控制。
裡面提到的暴擊機制非常吸引我。因為真隨機確實有個弊端,無法保證運氣不好的情況下多少次能觸發。
翻牌隨機呢能夠保證一輪當中必定觸發一次,但是如果用在遊戲領域它有一個非常要命的缺陷——存在真空期。何為真空期?我對其這麼定義:
概率大於0的事件在某些情況下100%不觸發,這些時期即為真空期。
舉個例子,有5張牌,其中只有一張是中獎。那麼,若第一次就翻到了中獎,也就意味著後面4次100%不會中獎。這是很要命的,賭徒都帶有僥倖心理,即便只有1%的機會也願意放手一博。但是,沒有哪個賭徒蠢到會去博0%的機會。因此,真空期是應該避免的。
上面提到的暴擊機制解決了這個問題
累計爆率,累計爆率設計思路和實現方法為:爆率的計算使用如下模式:每次攻擊如果不暴擊則下一次的暴率增加,直到產生暴擊以後累積的爆率復原。
例:單次基礎暴擊為12%,如果第一次沒暴擊則第二次暴擊為24%。如果第二次仍然沒暴擊則第三次暴擊為36%。第三次出現暴擊,累計被清空。第四次的暴擊率還原為12%。(很顯然,如果一直不暴擊,那麼暴擊一定會累計到100%以上產生必然的暴擊)。
當然,這個暴擊率遞增有點誇張了,但是它提供了一個思路與一種實現可能:
1.通過重置隨機率來避免真空期;2.這個綜合概率是可以算出來的。
概率推算
因此,翻牌隨機也只需要加一個簡單的重置即可:翻到中獎牌後,重新洗牌。存在的問題就是:概率如何計算?假設我想保證20%的中獎率,該有多少張牌?
用歸納法來遞推一下:
1張牌,機率1;
兩張牌,1/2的機率第1次中,1-1/2的機率第2次中(1/2),綜合=1/2+(1/2)/2=3/4;
3張牌,1/3的機率第1次中,(1-1/3) * (1/2)的機率第2次中(1/3),1 -1/3-1/3的機率第3次中(1/3),綜合=1/3+(1/3)/2+(1/3)/3=11/18;
看不出什麼,那麼繼續遞推——
4張牌,1/4的機率第1次中,(1-1/4) * (1/3)的機率第2次中(1/4),(1-1/4-1/4) * (1/2)的機率第3次中(1/4),1-1/4-1/4-1/4的機率第4次中(1/4),綜合=1/4+1/8+1/12+1/16=25/48;
...
好了,現在比較明顯了
n張牌,1/n第1次中,1/n第2次中,1/n第三次中...1/n第n次中。綜合=1/n + 1/(n * 2) + 1/(n * 3) + ... + 1/(n * n) = (1/n) * (1+1/2+1/3+...+1/n)
!!!真tm美妙的數學,目前還沒有公式能表示 1+1/2+1/3+...+1/n ,看來只能寫個指令碼算出前54張的對應概率了。
Python程式碼如下:
def poker(n):
rate = 0
for x in range(1,n+1):
rate = rate + 1/x
return (1/n) * rate
for x in range(1,55):
print("%d: %.2f" % (x, poker(x)*100) + "%")
公式:(1/n) * (1+1/2+1/3+...+1/n)
n=1...54時
1: 100.00%
2: 75.00%
3: 61.11%
4: 52.08%
5: 45.67%
6: 40.83%
7: 37.04%
8: 33.97%
9: 31.43%
10: 29.29%
11: 27.45%
12: 25.86%
13: 24.46%
14: 23.23%
15: 22.12%
16: 21.13%
17: 20.23%
18: 19.42%
19: 18.67%
20: 17.99%
21: 17.36%
22: 16.78%
23: 16.24%
24: 15.73%
25: 15.26%
26: 14.82%
27: 14.41%
28: 14.03%
29: 13.66%
30: 13.32%
31: 12.99%
32: 12.68%
33: 12.39%
34: 12.11%
35: 11.85%
36: 11.60%
37: 11.36%
38: 11.13%
39: 10.91%
40: 10.70%
41: 10.49%
42: 10.30%
43: 10.12%
44: 9.94%
45: 9.77%
46: 9.60%
47: 9.44%
48: 9.29%
49: 9.14%
50: 9.00%
51: 8.86%
52: 8.73%
53: 8.60%
54: 8.47%
因此,可以得出,若希望中獎率為20%(在翻牌重置模式下),則需要17或者18張牌。
概率校驗
一切似乎很美妙,輕而易舉推出了公式與概率表。
然而,用Java程式碼進行了一萬次抽取校驗,發現得出的概率與概率表相差甚遠。
private void pokerTest(int num) {
List<Integer> list = new ArrayList<>();
for (int x = 0; x < num; x++)
list.add(x);
Collections.shuffle(list);
Random random = new Random();
int luckyCount = 0;
for (int i = 0; i < 10_000; i++) {
int index = random.nextInt(list.size());
int lucky = list.remove(index);
if (lucky == num/2) { //取中間值作為中獎數
luckyCount++;
//抽中後重新洗牌
list.clear();
for (int x = 0; x < num; x++)
list.add(x);
Collections.shuffle(list);
}
}
System.out.println(" " + (luckyCount/10_000f));
}
執行pokerTest(17),得到0.11左右的數,與表中的20.23%差得有點多。
一步步校驗,
執行pokerTest(1),得到1.0,沒問題;
執行pokerTest(2),得到0.67,問題來了。
為什麼兩張牌的時候,概率會是0.67 ???
公式校準
回顧一下,兩張牌的概率我是這麼算的:
錯誤的演算法:
兩張牌,1/2的機率第1次中,1-1/2的機率第2次中(1/2),綜合=1/2+(1/2)/2=3/4;
考慮到了每次抽中的概率,考慮到了要除以抽中時所用的次數,但是!忽略了次數佔比。兩張牌,一次中的次數佔比是1/(1+2),兩次的次數佔比是2/(1+2),因此,兩張牌應該這麼算:
兩張牌,1/2的機率第1次中,1-1/2的機率第2次中(1/2),綜合=(1/2) * (1/(1+2))+((1/2)/2) * (2/(1+2))=2/3;
正確的公式應是:
n張牌,1/n第1次中,1/n第2次中,1/n第三次中...1/n第n次中。綜合=(2/(n * (n+1)) * 1/n + (2 * 2/(n * (n+1)) * 1/(n * 2) + ... + (n * 2/(n * (n+1)) * 1/(n * n) = (2/(n * (n+1)) * (1+1+1+...+1) = 2/(n + 1)
結果如此簡單:2/(n+1)。代入測試程式碼,發現基本沒有偏差。
正確Python程式碼:
def poker(n):
return 2/(n+1)
for x in range(1,55):
print("%d: %.2f" % (x, poker(x)*100) + "%")
P=2/(n+1)
1: 100.00%
2: 66.67%
3: 50.00%
4: 40.00%
5: 33.33%
6: 28.57%
7: 25.00%
8: 22.22%
9: 20.00%
10: 18.18%
11: 16.67%
12: 15.38%
13: 14.29%
14: 13.33%
15: 12.50%
16: 11.76%
17: 11.11%
18: 10.53%
19: 10.00%
20: 9.52%
21: 9.09%
22: 8.70%
23: 8.33%
24: 8.00%
25: 7.69%
26: 7.41%
27: 7.14%
28: 6.90%
29: 6.67%
30: 6.45%
31: 6.25%
32: 6.06%
33: 5.88%
34: 5.71%
35: 5.56%
36: 5.41%
37: 5.26%
38: 5.13%
39: 5.00%
40: 4.88%
41: 4.76%
42: 4.65%
43: 4.55%
44: 4.44%
45: 4.35%
46: 4.26%
47: 4.17%
48: 4.08%
49: 4.00%
50: 3.92%
51: 3.85%
52: 3.77%
53: 3.70%
54: 3.64%
因此,在翻牌重置模式下,若希望中獎率為20%,需要9張牌;若希望中獎率為5%,需要39張牌。
相關文章
- 探索JavaScript的this機制JavaScript
- 探索新技術機制
- 探索JavaScript執行機制JavaScript
- requestAnimationFrame 執行機制探索requestAnimationFrame
- 讓人沉浸遊戲的魅力機制:隨機與策略遊戲隨機
- golang 釋放記憶體機制的探索Golang記憶體
- webpack 原始碼探索之外掛機制Web原始碼
- 隨機生成中文姓名,手機號,郵編,住址(Java)隨機Java
- 探索 React 中 es6 的繼承機制React繼承
- ElasticSearch 文件(document)內部機制詳解Elasticsearch
- HDFS 02 - HDFS 的機制:副本機制、機架感知機制、負載均衡機制負載
- Java基礎(五):包機制、文件註釋Java
- 美團針對Redis Rehash機制的探索和實踐Redis
- 非酋的福音?談一談遊戲內的偽隨機機制以及實現遊戲隨機
- python生成隨機數、隨機字串Python隨機字串
- Python PIL模組隨機生成中文驗證碼Python隨機
- Python如何隨機生成1到100的隨機數?Python隨機
- 實現不可逆加密檔案:探索 GodoOS 的安全機制加密GoOdoo
- 暴雪隨機術:《暗黑破壞神》創造經典遊戲機制的祕籍隨機遊戲
- 明明的隨機數隨機
- 中文分詞的探索,CRF(條件隨機場)和HMM(隱馬爾可夫模型)用於分詞的對比,以及中文分詞的評估中文分詞CRF條件隨機場HMM隱馬爾可夫模型
- Linux Shell 生成隨機數和隨機字串Linux隨機字串
- 探索計算機內部的神秘語言:二進位制的魅力計算機
- Matlab 隨機生成兩個數值之間的隨機數Matlab隨機
- starrycan的pwn隨筆——ELF檔案和延遲繫結機制
- 隨機數隨機
- iOS探索 動態方法解析和訊息轉發機制iOS
- 響應式流的核心機制——背壓機制
- 實現一個炫酷的隨機標籤排列效果(顏色隨機,大小隨機,成菱形排列的列表)隨機
- 書海拾貝|開發藝術探索之 android 的訊息機制Android
- 隨機森林的祕密隨機森林
- Java 控制隨機數出現的機率Java隨機
- 帝國CMS萬能標籤呼叫隨機文章的方法(按表隨機和按照本欄目隨機)隨機
- Thread的interrupt機制thread
- PHP 的 SESSION 機制PHPSession
- Java的反射機制Java反射
- Java 的 SPI 機制Java
- Redis的事件機制Redis事件