此前,在公司的项目开发中,我负责着手解决这样一个问题:在斗地主游戏中,根据玩家出的牌分析出这手牌的牌型。
大家知道,在斗地主游戏中,总计有十一种牌型:
火箭:即双王(大王和小王)。
炸弹:四张同数值牌(如四个7)。
单牌:单个牌(如红桃5)。
对牌:数值相同的两张牌(如梅花4+方块4)。
三张牌:数值相同的三张牌(如三个J)。
三带一:数值相同的三张牌 + 一张单牌或一对牌。例如: 333+6或444+99
单顺:五张或更多的连续单牌(如:45678或78910JQK)。不包括2点和双王。
双顺:三对或更多的连续对牌(如:334455、7788991010JJ)。不包括2点和双王。
三顺:二个或更多的连续三张牌(如:333444、555666777888)。不包括2点和双王。
飞机带翅膀:三顺+同数量的单牌(或同数量的对牌)。
如:444555+79 或333444555+7799JJ
四带二:四张牌+两手牌。(注意:四带二不是炸弹)。
如:5555+3+8或4444+55+77。
那么,如何由玩家出的牌分析出这手牌到底是哪一种牌型呢?
在我们试着用程序解决这个问题之前,先来回顾一下在现实的生活中是如何分辨一手牌的牌型的。在斗地主游戏中,确定不同牌型的一个重要依据是看这手牌中有多少张牌的数字是相同的。比如一手这样的牌:梅花2+方块3+红桃3+黑桃3,在我们的思维中,首先会计算有最多相同数字的那些牌的个数,也就是这里的三个3,在这里,3总计出现了3次。根据最多出现相同数字的情况,我们可以把一手牌先分成四种情况:
1、所有数字只出现一次
2、相同数字的牌出现两次
3、相同数字的牌出现三次
4、相同数字的牌出现四次
5、不可能出现的情况:相同数字的牌出现大于四次或小于1次。
其中,在以上的1、2、3、4中又可能分为多种情况,比如在1中,虽然相同数字最多只出现一次,但不能因此就断定它是单张,它也有可能是双王(这里假定大小王的数字不相同)或单顺;在2中,出现两次的情况下,又进一步分为:对子和双顺两种情况;在3中,出现三次的情况下,可能有以下牌型:单三张,三带一,三顺或飞机;在4中,出现4个相同数字牌的时候,可能有以下牌型:炸弹和四带二。
为了建立以上的这种分析模型,我们需要对出的牌进行排序和统计,找出最大的相同个数及相同的数字,再进一步分析它的特征直到最终确定当前牌的牌型。用于实现牌型分析伪过程如下:
注:cardlist为所出牌的列表,cardcount为所出牌的个数。二维数组cardArray[0..12,0..1]是用于分析的辅助数据结构。
1、对cardlist按牌的数字大小进行升序排序
2、对carlist中的每张牌顺序进行以下操作
将cardlist中牌的数字记入cardarray的低维中,即首先记cardlist[0]的数字于cardarray[0,0]中,并将cardarray[0,1]置为1,然后顺序取出cardlist中的后继牌,判断后继牌是否等于cardarray当前位置的cardarray[X,0]值,如果等于,则在card[x,1]中加1,以求得相同牌的个数,如果不等于,则在新单元cardarray[X+1,0]中记入cardlist当前牌的数字,并把cardarray[x+1,1]置为1。如此循环,对cardlist中的每张牌都进行扫描后,cardarray数组中,低维存放的就是当前这手牌中出现的所有数字,而在其对应的高维中则存放这些数字出现的次数。由这个二维数组,我们便可以初步判定这手牌的牌型。
这是我在实际工作中所采用的牌型分析方法,此方法最初由我们的teamleader提出,后来我作了些小小改动,不知有没有作相同问题研究的朋友,如果有更好的方法可以判断,请不吝赐教。