斗地主这个游戏的流程主要有,洗牌,发牌,出牌,而最重要的便是出牌了,出牌里包含着游戏的牌型,所以这里就先给大家讲讲我进行牌型判断的思路。
"""
牌型定义: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()
思路基本都写在代码的注释里了,我想到的牌型基本都验证完毕了,如果有其他牌型却未出现在代码里的,或者你们有更优的想法或思路,或者是我的代码里会有某些错误,都可以通过博客下面的留言跟我一起探讨哦