哇,好久好久没写东西啦。。。
这两天实现了一个简单的游戏引擎,可以发牌,可以比较两手牌的大小
由于最近都在倒腾Golang,所以用GO实现的。这阶段过后准备用这个引擎来实现一个简单的AI对战,现在先记录一下
接下来我假设你已经懂游戏规则和俗语了
首先是牌的储存,2~~A,一共13张牌,我用的是一个14位的二进制区间来储存的,比如2-A,将表示为:11111111111110,辣么第一位是干啥的呢,请继续看下面
这样的储存方式除了省空间外还有什么优势呢?我们顺子的判断为例:
例如顺子10JQKA,在二进制区间将表示为11111000000000,叫它S
现在我们有手牌2 3 10 J Q K A,那么它的二进制表示是11111000000110,叫它T
那么T&S==S的话,就可以说明T包含一个顺子,并且顺子是10JQKA
S转化为10进制的话是15872
类似的我们将所有可能的顺子预先保存好,如下表(10用T表示):
----------------------------------------------------------------------------------------------------
TJQKA | 9TJQK | 89TJQ | 789TJ | 6789T | 56789 | 45678 | 34567 | 23456 | A2345 |
15872 | 7936 | 3968 | 1984 | 992 | 496 | 248 | 124 | 62 | 31 |
-----------------------------------------------------------------------------------------------------
由于德州扑克里面A 2 3 4 5是最小的顺子,现在你可以明白二进制区间里第0位的作用了,和最高位一样也是保存A
我们维护一个容量为4的int数组straight,它表示四个花色中每种花色的牌,储存原理见开头,它将被用来快速的判断同花顺,同时还可以用来判断是否为同花
再维护一个int变量hand,它表示所有手牌的并集,不分花色。它将被用来快速的判断是否为顺子
最后维护一个容量为13的int数组count,它用于对每种牌值出现的次数计数
我们将所有牌型做一个分级:
皇家同花顺:10
同花顺 :9
四条 :8
葫芦 :7
同花 :6
顺子 :5
三条 :4
两对 :3
一对 :2
高牌 :1
比较的时候先比较两手牌的等级,等级相同的情况下,我们进一步分析每一副手牌的value值。
我的value的算法如下:
对你的手牌进行排序,排序规则是出现次数多的优先,次数相同的则值大的优先,比如:
7 8 4 2 2 A K,排序后为:22AK874,可以理解为16进制:0x22AD874。
需要注意的是,顺子和同花不适应此算法,顺子的value就是该顺子的最高牌;同花的value是该花色的牌并集(具体读者可以自己思考)
各种牌型的判断以及比较:
1、皇家同花顺 royal flush
这个最简单了,直接用四个花色的牌集(详见straight数组),去和15872相与即可(原理见上)
一场牌局只可能出现唯一皇家同花顺,所以只需要记录等级即可,因为只可能win or tie(五张公牌)
2、同花顺straight flush
和皇家同花顺类似,从大到小遍历所有可能的顺子,和它们做与操作。value值是该顺子中最大的高牌
3、四条 four of a kind
维护一个数组count []int用于对每一种牌值进行计数即可。
还有一种方法是将四种花色的牌集相与,最后二进制区间内还是1的那些就是我们要的。
4、葫芦 full house
通过count数组先遍历有没有出现三次的,有的话,再遍历有没有出现2次的
5、同花 flush
有两个方法,一个是对每一个花色的牌集进行遍历,看看二进制集合里有没有5个1
第二个方法详见代码,判断同花的逻辑处
6、顺子 straight
取所有花色牌的集合,去和所有可能的顺子做与操作
7、三条 three of a kind;两对 two pairs; 一对 one pair
运用count数组计数器
源码开源在github上:https://github.com/SongLiangChen/TexasHoldem.git