偶然间看到了“扑克牌斗牛”游戏规则,对其中各种“牛”的概率问题产生了兴趣,故研究了下游戏规则后使用Python实现了五张牌各种“牛”的判断规则,欢迎各位读者测试指正。
废话不多说,直接上代码:
from itertools import combinations
import random
def createCards():
cardType = ['梅花', '方块', '红桃', '黑桃']
cardNum = ['A', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K']
cardPoints = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] * 4
cardList = [cT + str(cN) for cT in cardType for cN in cardNum]
cardDict = {}
for i in range(len(cardList)): cardDict[cardList[i]] = cardPoints[i]
return cardDict
#发牌方法,任意取出五张牌后,返回卡组信息列表(卡组列表,点数列表)及卡池剩余牌字典
def dealCards(cardDict):
cardLists = random.sample([key for key in cardDict.keys()],5)
cardMap = {}
for card in cardLists: cardMap[card] = cardDict[card]
pointList = [point for point in cardMap.values()]
playerList = [cardLists,pointList]
for card in cardLists:
cardDict.pop(card)
return playerList,cardDict
#将大于10的花牌点数设置为10
def cardRealpoints(num):
if num in [11,12,13]:
return 10
else:
return num
#通过卡牌点数获取卡牌
def pointCardMapping(point):
cardNum = ['A', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K']
return cardNum[point-1]
#以下为各种牛的判断方法--------------------------------------------
#判断是否为炸弹 返回值炸弹点数,是否为炸弹
def bombList(pointList):
for item in pointList:
if pointList.count(item) == 4:
return pointCardMapping(item),True
else:
return None,False
#判断是否为五小 返回值是否为五小
def fiveLittle(pointList):
littleList = list(filter(lambda point:(point<5),pointList))#将点数小于5的点数取出成新列表
# print(littleList)
if len(littleList)== 5 and sum(littleList) == 10:#5张牌点数均小于5 且和为10
return True
else:
return False
#判断是否为五花
def fiveFlower(pointList):
flowerleList = list(filter(lambda point: (point > 10), pointList)) # 将点数大于10的点数取出成新列表
# print(flowerleList)
if len(flowerleList) == 5 and bombList(pointList)[1] == False: # 5张牌点数均大于10 且卡组中无炸弹
return True
else:
return False
#判断是否为四花
def fourFlower(pointList):
flowerleList = list(filter(lambda point: (point > 10), pointList)) # 将点数大于10的点数取出成新列表
# print(flowerleList)
lastList = [point for point in pointList if point not in flowerleList]
# 4张牌点数均大于10 且卡组中无炸弹且剩余一张牌点数为10
if len(flowerleList) == 4 and bombList(pointList)[1] == False and (len(lastList)== 1 and sum(lastList) == 10):
return True
else:
return False
#卡牌点数计算器 计算卡组点数列表中的点数和
def cardCalculator(pointList):
sumPoints = 0
for points in pointList:
sumPoints += cardRealpoints(points)
return sumPoints
#中间方法任取三张牌为10的倍数,并返回其组合方式(集合,集合中存元组,如{(1, 2, 7), (1, 1, 8)})
# J Q K 按照10点来计算
def getTen(pointList):
getList = set(combinations(pointList,3)) # 五取三 组合
# 使用点数计算器算出三张牌之和为10的倍数的组合
tenList = [itemList for itemList in getList if cardCalculator(itemList) % 10 == 0]
#讲组合去重
tenSet = set(tuple(tenList))
return tenSet
#判断牛10-牛1或无牛 入卡组存在多牛 则返回最大
def tenBull(pointList):
tenSet = getTen(pointList)
tenDict = {}
#如果不为炸弹、五小、五花、四花且有牛
if len(tenSet) > 0 and bombList(pointList)[1] == False and fiveLittle(pointList) == False and fourFlower(pointList) == False and fiveFlower(pointList) == False:
for ten in tenSet:
#使用点数计算器算出剩余两张牌之和并判断
if (cardCalculator(pointList)-cardCalculator(ten)) % 10 == 0:
tenDict[''.join([str(i)+' ' for i in ten])+'|'+''.join([str(t)+' ' for t in pointList if t not in ten])] = 10
else:
tenDict[''.join([str(i)+' ' for i in ten])+'|' + ''.join([str(t)+' ' for t in pointList if t not in ten])] = (sum(pointList)-sum(ten)) % 10
# print(bombList(pointList),fiveLittle(pointList),fourFlower(pointList),fiveFlower(pointList),tenDict)
#如果同时存在多种牛 则返回牛数最大的
if len(tenDict) > 0:
return max(zip(tenDict.values(),tenDict.keys()))
else:
return None
#以上为各种牛的判断方法--------------------------------------------
def gamePriority(playerList):
if bombList(playerList[1])[1]:
return '卡组{}为炸弹'.format(playerList[0])
elif fiveLittle(playerList[1]):
return '卡组{}为五小'.format(playerList[0])
elif fiveFlower(playerList[1]):
return '卡组{}为五花'.format(playerList[0])
elif fourFlower(playerList[1]):
return '卡组{}为四花'.format(playerList[0])
else:
result = tenBull(playerList[1])
if result == None:
return '卡组{}无牛'.format(playerList[0])
else:
return '卡组{}为牛{}'.format(playerList[0],result[0])
def createLogs():
pass
def game():
cardsMap = createCards()
cardDicts = cardsMap.copy()
n = 1
logfile = open(r'D:\File\pythonfiles\gamelog.txt','a+')#牌组信息写入文件
print('*'*50,file = logfile)
while len(cardDicts)>=5:
playerList, cardDict = dealCards(cardDicts)
cardDicts = cardDict
result = gamePriority(playerList)
print('第{}次抽牌,{}'.format(n,result),file = logfile)
n += 1
if __name__ == '__main__':
game()