一個感興趣的嘗試,計算德州撲克勝率


 前一陣子挺喜歡看德州撲克的比賽,感覺很好玩,不知道大家有沒有玩過,簡單說下規則就是
手上的兩張底牌 + 5張桌上的公共牌,一共7張牌,組合成最大的 5張卡 玩家之間進行比較大小,大者獲勝,平則平分。
具體大小可以參考以下排序

我整理了思路,這個勝率計算有兩個關鍵點:
1、如何確定7張牌中的最大牌型以及如何確定5張牌的牌型是什么
2、如何計算五張河牌(公共牌)都沒翻出的情況下計算兩組(或多組)底牌之間相互的勝率

先說說問題的第一點
 這個計算量沒有什么,就是要德州撲克的規則用代碼形式寫出來
比如計算順子時候 我只需要將5張牌排序,然后每張都比他的前一張大就行(A2345的情況單獨處理),或者校驗牌型是否是四條時候,檢測5張牌中時候有4張相同的數字牌就行,為此,我需要給每個牌型寫一個校驗的方法,此外,同花順是可以復用同花以及順子牌型的方法的,然后檢驗到5張牌屬於什么牌型之后(記個對象參數代表牌型,可以將不同牌型的牌組過濾比較大小),我再計算它的同牌型的大小,列如葫蘆(33355),是先比較三條的數字,如果三條的數字相等再比較對子的數字,那么我們可以記它的第一個比較參數first = 3, 第二個比較參數 second = 5,那么這樣,同牌型之間的大小比較只要在幾個參數 依次比較 之后即可知道大小。
 接下來就是怎么確定7張牌中最大的是哪5張呢,我想了想,沒有什么更好的辦法,只能遍歷, 為此我們需要花 C75次 = 21次的循環之后才能得到 最大的 5張牌的牌組

然后我們說說問題的第二點
 其實第二點我是考慮的比較久的,第一點畢竟比較無腦,是一些死的規則,我第一點考慮的是遍歷所有的可能性,我想了想情況, 兩組底牌已經消耗了 4張牌 ,還有 50張牌是未知的
那么那5張河牌的可能性就有 C50 5 = 2118760 種可能性, 再加上7張牌中要取得最大牌需要循環 21次, 另外要計算兩組底牌, 那么就是 2118760 * 21 *2 = 88987920 次的計算
 算出了這個結果之后我有點無力,將近1億次的牌組比較,我覺得不可以通過遍歷去做這個概率計算,否則我的電腦得跑半天,我測試都測不了(這是出自我的牌組計算大小的算法前提下的,為此我在代碼中創建了大量的對象去記錄每個牌組的信息),我能想象到我的算法是循環不了多少次的,1億次,可能直接就內存對象溢出搞宕機了(其實在這點上,應該對算法的對象存儲以及一些計算的算法進行優化,或者通過別的算法途徑,應該可以提升大量的時間,再將時間縮短到原來的1/10,不過為了快速實現這個勝率計算的demo,我決定還是先將demo跑出來)。
 我估計我的算法理想情況能在循環十萬次左右的時間跑1s秒就好。
 遍歷不行,受到其他未知情況下的概率計算的一些方案的啟發,我決定用簡單的隨機數進行比較,隨機從1-54中取 5個數字(若是底牌存在或者重復則舍棄再取一次),然后對應poker的花色以及數字,有了隨機的5張河牌,那么就可以知道哪個底牌是比較大的了。
 我用這套代碼進行了10W次的循環嘗試,結果單線程10W次居然需要10S左右的時間,為了得到更為准確一點的數據,我是不允許循環少於10W次的,我沒有去優化算法方面的代碼,直接將循環分割成十個多線程去執行,以此來縮減一些時間,最后10W次的代碼執行結果是在 1s中左右。

demo跑完了,但是我的算法究竟准不准確呢,有沒有哪些地方被我不小心寫錯了導致了錯誤的勝率然而我自己也看不出來的?
幸好,我之后在傳奇撲克的網站上看到了這個概率計算的軟件pokerstoove,pc端運行,用它的勝率結果作為判斷依據准沒錯,我接下來開始進行實驗測試。
我選擇用AK跟口袋對子AA比較勝率
這是pokerstove的結果:

我的接口參數與結果,循環10W次,耗時1.1秒,勝率幾乎相等:


就一組情況對比不夠明顯,我們再來比較一下別的
用QQ比較77
實驗結果stove:

我的代碼計算結果:

多對比幾組,再試試89打23
stove:

我的程序:


通過上面幾組實驗的比較,可以確定代碼的判定計算邏輯是沒有問題的,隨機河牌次數越大是概率應是越准確的。
另外,stove的概率是沒有包含平局的場景,所以它的兩個勝率相加為100%,而我的程序相加是會超過100%的,超出的那部分就是和牌的場景的概率。
為了測試地更准確,我又進行了各種牌組的比較(在這上邊就不貼了)
結果都是對的,無論是口袋對子,Ak,22,89還是什么牌型之間的比較,勝率都是跟stove相等的,至此,我的demo也就告一段落了,已經完成了目標,我也不想再去優化那塊算法的代碼(雖然應該還有很大的提升空間,但是寫了兩三個小時有點小累),
大家有興趣可以去我的git上把項目拷下來試玩一下,https://github.com/961094037/demo-spring-boot 代碼在poker的分支上


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM