一个感兴趣的尝试,计算德州扑克胜率

 前一阵子挺喜欢看德州扑克的比赛,感觉很好玩,不知道大家有没有玩过,简单说下规则就是
手上的两张底牌 + 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的分支上

posted @ 2020-03-17 15:07  星期天去哪玩o  阅读(7189)  评论(5编辑  收藏  举报