斗地主这个游戏的流程主要有,洗牌,发牌,出牌,而最重要的便是出牌了,出牌里包含着游戏的牌型,所以这里就先给大家讲讲我进行牌型判断的思路。

"""
牌型定义:1.单张
         2.对子
         3.三不带
         4.炸
         5.三带一
         6.连对
         7.顺子
         8.飞机不带
         9.飞机带单
         10.飞机带对子/三带二
         11.四带2
         12.四带一对
牌型判断前提:1.输入的列表为已经从上到下排列的列表
						  2.只针对一副牌的情况
						  3.一组列表可能代表着多种牌型,这里没有进行并行判断。
						  4.这里的列表用“0-13”分别对应扑克牌的“3-鬼”,这里暂时不判大小不区分大小鬼
"""
class doudizhu:
    #单张
    def dan(self):
        return 1
    #对子
    def dui(self, l):
        if l[0] == l[1]:
            return 2
        else:
            return 99
    #三不带
    def san(self, l):
        if l[0] == l[2]:
            return 3
        else:
            return 99
    #炸弹
    def zha(self, l):
        if l[0] == l[3]:
            return 4
        else:
            return 0
    #三带一
    def sanyi(self, l):
        if l[0] == l[2] or l[1] == l[3]:
            return 5
        else:
            return 0
    #三带二(未用,与飞机2合并)
    def saner(self, l):
        if (l[0] == l[2] and l[3] == l[4]) or (l[2] == l[4] and l[0] == l[1]):
            return 6
        else:
            return 0
    #顺子(思路:后一个数要比当前数1,有一个发生错误直接返回0)
    def shunzi(self,l):
        paixing = 0
        for i in range(len(l)-1):
            if l[i+1]-l[i] == 1:
                paixing = 7
            else:
                return 0
        return paixing
    #连对(思路:先将长度对半折,同样要判断后2个数比当前数大1,且后一个数与当前数相等)
    def liandui(self,l):
        paixing = 0
        for i in range(int(len(l)/2)-1):
            if l[(i+1)*2]-l[i*2] == 1 and l[i*2] == l[i*2+1]:
                paixing = 6
            else:
                return 0
        return paixing
    #飞机0(思路:每隔3个数后一个数都要比当前数大1,3个数内,后一个数要相等于当前数,未符合条件直接返回0)
    def feiji0(self,l):
        paixing = 0
        for i in range(len(l)-1):
            if (i+1)%3 == 0 and l[i+1] - l[i] == 1:
                paixing = 8
            elif l[i] == l[i+1]:
                paixing = 8
            else:
                return 0
        return paixing
    #飞机1(思路:计算3个数相同的组合有几组,再与其他未达到3个相同的总牌数比较,相等则正确)
    def feiji1(self, l):
        a = 1
        m = []
        for i in range(len(l)-1):
            if l[i] == l[i+1]:
                a += 1
            else:
                a = 1
            if a == 3:
                m.append(l[i])
                a = 1
        if len(l) - len(m) == len(m)*3:
            return 9
        else:
            return 0
    #飞机2(思路:与飞机1类似,不同的是,此处的对子也需要统计,还需要考虑特殊情况(用炸做对子))
    def feiji2(self, l):
        a = 1
        b = 0
        m = []
        for i in range(len(l)-1):
            if l[i] == l[i+1]:
                a += 1
            if a == 3:
                if l[i] != l[i+2]:
                    m.append(l[i])
                    a = 1
            elif a == 2:
                if l[i] != l[i+2]:
                    b += 1
                    a = 1
            elif a == 4:
                b += 2
            else:
                a = 1
        if b == len(m):
            return 10
        else:
            return 0
    #四带2(思路,四带2就3种情况,我就不多说了)
    def sidaier1(self,l):
        if l[0] == l[3] or l[1] == l[4] or l[2] == l[5]:
            return 11
        else:
            return 0
    #四代两对(思路:与四带二一样也就3种情况,就是条件还要多加对子判断)
    def sidaier2(self, l):
        if l[0] == l[3] and l[4] == l[5] and l[6] == l[7]:
            return 12
        if l[2] == l[5] and l[0] == l[1] and l[6] == l[7]:
            return 12
        if l[7] == l[4] and l[0] == l[1] and l[2] == l[3]:
            return 12
        return 0
    #这个函数主要就是,对牌型判断前的筛选工作,比如,一张牌就只能是单张,2张牌要先判断是不是王炸等等
    def paixing(self, l):
        m = len(l)
        paixing = 0
        if m == 1:
            paixing = self.dan()
        elif m == 2:
            #判断王炸
            if l[0] == 13:
                paixing = 4
            else:
                paixing = self.dui(l)
        elif m == 3:
            paixing = self.san(l)
        elif m == 4:
            #优先判断炸
            paixing = self.zha(l)
            #再三带一
            if paixing == 0:
                paixing = self.sanyi(l)
        elif m >= 5:
            # 这里的判断基本是并行的,前提是前面的判断没获取到类型
            #大于5张都判断一次顺子
            paixing = self.shunzi(l)
            if paixing == 0:
                #然后就是连对判断
                if m%2 == 0:
                    paixing = self.liandui(l)
            if paixing == 0:
                #飞机不带
                if m%3 == 0:
                    paixing = self.feiji0(l)
            if paixing == 0:
                #飞机带一
                if m%4 == 0:
                    paixing = self.feiji1(l)
            if paixing == 0:
                #飞机带对子
                if m % 5 == 0:
                    paixing = self.feiji2(l)
            if paixing == 0:
                #四带二
                if m == 6:
                    paixing = self.sidaier1(l)
            if paixing == 0:
                #四带一对
                if m == 8:
                    paixing = self.sidaier2(l)
        if paixing == 0:
            paixing = 99
        return paixing

    def chupai(self):
        l = [3,3,3,4,4,4,5,5,5,5]
        paixing = self.paixing(l)
        if paixing == 1:
            print("单张")
        elif paixing == 2:
            print("对子")
        elif paixing == 3:
            print("三不带")
        elif paixing == 4:
            print("炸")
        elif paixing == 5:
            print("三带一")
        elif paixing == 6:
            print("连对")
        elif paixing == 7:
            print("顺子")
        elif paixing == 8:
            print("飞机不带")
        elif paixing == 9:
            print("飞机带一")
        elif paixing == 10:
            if len(l) == 5:
                print("三带二")
            else:
                print("飞机带对子")
        elif paixing == 11:
            print("四带二")
        elif paixing == 12:
            print("四带两对")
        elif paixing == 99:
            print("牌型错误")
        else:
            pass
if __name__ == "__main__":
    dou = doudizhu()
    dou.chupai()

思路基本都写在代码的注释里了,我想到的牌型基本都验证完毕了,如果有其他牌型却未出现在代码里的,或者你们有更优的想法或思路,或者是我的代码里会有某些错误,都可以通过博客下面的留言跟我一起探讨哦

07-14 16:51