基于扑克概率的编程算法研究

2013-04-13 07:21
科技视界 2013年14期
关键词:张牌黑桃胜率

陈 思

(福州大学 数学与计算机科学学院,福建 福州 350000)

0 背景

德克萨斯扑克全称Texas Hold’em poker,中文简称“德州扑克”。它是一种玩家对玩家的公共牌类游戏。一张台面至少2人,最多22人,一般是由2-10人参加。德州扑克一共有52张牌,没有王牌。每个玩家分两张牌作为“底牌”,五张由荷官陆续朝上发出的公共牌。开始的时候,每个玩家会有两张面朝下的底牌。经过所有押注圈后,若仍不能分出胜负,游戏会进入“摊牌”阶段,也就是让所剩的玩家亮出各自的底牌以较高下,持大牌者获胜。因技巧性强,易学难精又被称为“扑克游戏中的凯迪拉克”。

在这个游戏里,如何根据手头的牌以及桌面上的牌计算概率,成为胜负的关键。与一副牌的已知牌型计算不同,德州扑克不但需要计算牌型的RANK(即排名)值,更需要计算出当前牌型的具体胜率。其中具体的胜率计算非常复杂,笔者将在本文中探讨一种可行的方式。

1 游戏介绍

由于本文为概率计算介绍,不在赘述德州扑克中关于筹码的计算规则,仅把扑克的基本胜负规则做一个阐述。

每个玩家拥有两张底牌,桌面上将陆续发至5张公共牌。当全部5张公共牌发完后,玩家用自己的2张底牌和5张公共牌结合在一起,选出5张牌,不论手中的牌使用几张(甚至可以不用手中的底牌),凑成最大的成牌,跟其他玩家比大小。

比牌先比牌型,大的牌型大于小的牌型,牌型一般分为10种,从大到小为:皇家同花顺(royal flush):由AKQJ10五张组成,并且这5张牌花色相同;同花顺(straight flush):由五张连张同花色的牌组成;4条(four of a kind):4张同点值的牌加上一张其他任何牌;满堂红(full house)(又称“葫芦”):3 张同点值加上另外一对;同花(flush):5 张牌花色相同,但是不成顺子;顺子(straight):五张牌连张,至少一张花色不同;3条(three of a kind):三张牌点值相同,其他两张各异;两对(two pairs):两对加上一个杂牌;一对(one pair):一对加上 3张杂牌;高牌(high card):不符合上面任何一种牌型的牌型,由单牌且不连续不同花的组成。

2 问题详述与分解

在本文中,笔者们的主要问题就是,需要计算玩家的胜率。换句话来说,假设当玩家持有AK(不同花色)时,桌面上为2,3,4,K,Q,且此时共同游戏的玩家有9名 (即竞争对手有8名),这种情况的胜算是多大,就是笔者们需要计算的值。

由于笔者们对于另外8个竞争对手手上的牌一无所知,计算胜率时,笔者们需要穷举所有的8名玩家可能出现的所有牌型,并一一分析,最后得出实际胜率。

为了研究简便,笔者们将游戏被分解为这样的问题:

1)一副牌中,任意取出五张,需要程序马上计算出它在所有牌型中的排名;

2)已知七张牌中,计算这7张牌能凑出的最大牌型;

3)根据当前公共牌面、人数,穷举所有情况,并一一对比从而计算胜率(后续内容将证明这种方式并不科学并会给出解决方案)。

本论文中将解决以上问题,并编写为IPHONE APP。解决问题时,考虑到IPHONE处理器的处理水平,解决过程进行过专门的优化处理。

2.1 牌型的排名

计算牌型的排名涉及到牌型之间的对比。由于上述的分解步骤中,第三部(即穷举步)将进行大数量级的牌型对比,在这种对比中,每次都调用牌型分析函数是不明智的,笔者们需要将牌型以及其对应的排名一次性计算出来,并予以储存,方便快速调用。

一副扑克一共有52张,从其中抽出5张的可能性一共有:2598960种可能性。如果将以上情况一一存储(需要存储牌值以及排名),至少需要20M左右的存储空间。这不但会让整个应用程序变的臃肿,更会大幅降低检索速度。

本文采取的方式如下:

2.1.1 考虑到德州扑克的牌型大小对比时,不考虑花色。即红桃10JQKA与黑桃的10JQKA被认为是一样大。每次计算某5张牌的值时,用这种方式表示当前牌型:

1)不管牌型花色;

2)计算牌型中重复的牌,并对其计数。

编码规则:

笔者设立了一个长度为52的数组,其中0,4,8,12….48所有被4整除的整数将分别用于代表扑克上的数字,规则是n代表(n/4)+1。在这里笔者们将扑克A计数为1,K计数为13,Q计数为12,而J技术为11。而无法被4整除的数,将用来代表上述数字的牌面,出现了多少次。

举例来说:红桃A,黑桃A,方块K,梅花K,黑桃6这个牌型,经过以上整理,被编码为:2,50,20。 (例 3.1)

用数学表达来说,假设编码后的数字为i,j,k,则代表原牌型为:

(i%4+1)张的(i-i%4)/4+1,(j%4+1)张的(j-j%4)/4+1,(k%4+1)张的(kk%4)/4+1

从以上例子来看,2,50,20并不仅仅代表红桃A,黑桃A,方块K,梅花K,黑桃6这种情况,实际上,它代表了所有一对A,一对K以及一张单张6的牌型而不管花色如何。

2.1.2 为了方便数据存储并保证牌型的唯一性(即确保不一样的牌型笔者们会以不同的数据存储起来),笔者采用64位随机数来代表所有牌型。

代码如下:

PNC数组即代表不同数字(1-K)以及不同数量(1张到4张)的所有情况。以之前的“红桃A,黑桃A,方块K,梅花K,黑桃6”牌型为例,如果需要将该牌型进行唯一标识,采取以下方式:

Zobrist=PNC[2]^PNC[20]^PNC[50];//Zobrist即计算出的牌型值,它是唯一的。

2.1.3 有了以上的数组后,即可以通过遍历所有牌型情况,给每一种牌型进行评分。为了方便计算,采取的方法是将牌型由大到小进行排列,将最大的牌型记为1分,第二大的牌型记为2分,相同的牌型分值相同,以此类推。

相关代码示例如下:

2.2 概率的计算

根据2.1节所述,我们可以知道当所有桌面牌都被发下后,可以通过简单的排列组合得出手上两张牌与桌面5张牌结合中最大的牌型,举例来说:

玩家手牌:红桃K,黑桃A

桌面牌:梅花 K,方块K,红桃Q,黑桃 J,方块 10

则最大牌型为顺子,即:黑桃A,方块K(或者其他两色K),红桃Q,黑桃J,方块10。接下来,需要根据手头的牌型以及桌面的5张牌,计算胜率。由于德州扑克的复杂性,前面说到,如果要精确计算概率,那么其数量级是非常庞大的,当玩家超过3名以后,当前的计算机也无法完成这样的计算任务。(具体算法如下)

一般德州扑克的玩家是6名以上,这样计算胜率根本是不现实的。但是,我们注意到,概率计算除了精确计算以外,我们可以采取非精确估计法。

举例来说,玩家的某个牌型,我们并不清楚其究竟是否会获胜,我们可以随机生成其余玩家的牌型,我们把生成完毕的情况称为一组牌局,每随机生成一组牌局,我们就对比当前玩家与其他随机生成玩家的牌型,以计算当前玩家是否获胜,如果获胜,就把胜利局数计数器加1,当模拟牌局数量超过某个值时,计算模拟局中当前玩家获胜的次数与总牌局数量的比值,即为我们想要的胜率。

这样,我们将一个天文数字的牌局对比,下降到计算机可以接受的程度,以6名玩家为例,总共需要计算的牌型情况为:

如果我们设置总局数为10000局,则计算总数为1260000,该数量级对于计算机来说非常轻松,实际测试中,一台普通配置的个人电脑可以在3秒内完成该计算。局数越多,则计算出的概率与实际值就越接近,根据2玩家小规模测试,总局数在2000局以上时,计算出的概率已经非常接近于真实值,局数大幅增加虽然让数字更加接近,但实际意义并不大。

3 总结

通过牌型的存储与计算以及一种基于概率的非精确算法,我们从一定程度上解决了德州扑克的概率问题,在实际应用中,我们发现这种方法的准确率较高,已经可以从一定意义上指导牌局。当然,随着技术的发展,应该会有更加先进的算法出现,本文所述的方法也仍有一定的提升空间(如加大模拟局的总数,采取后台计算等等),后续笔者会持续跟进本项目研究。

猜你喜欢
张牌黑桃胜率
一种生成残局数据库的倒推算法
基于预期收益策略与UCT的德州扑克算法
牌友黑桃
牌友黑桃
扑克牌
2014—2015年中国女子篮球职业联赛单节得失分与比赛结果相关性分析
CBA球队主客场胜率及得失分与比赛结果排名的相关性研究
那一夜,以背叛的姿态做你贞洁的新娘