Python实现炸金花游戏的示例代码
今天的第二个作品,哈哈哈哈,搞起来感觉还挺有意思的,不过代码里纸牌J,Q,K,A几个数字被我替换成了11,12,13,14......主要是没有想到简单的办法让其比较,索性都用数字了,我太菜了,希望有大佬指点一下。
代码如下:
import random #导入随机数函数 def puke(): """ 生成一副52张的扑克牌(除去大小王) :return: """ list1 = ['黑桃', '红桃', '方块', '梅花'] list2 = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] list3 = [] for i in list1: for j in list2: dict1 = {i: j} list3.append(dict1) return list3 def func(num): """ 判断随机生成的三张扑克类型,对不同类型的牌 底分进行相应的翻倍 其中num参数返回的是对玩家牌型计算后的分数。 (最小单张是:2, 11,12,13,14 分别代表:J,Q,K,A) :param num: :return: """ user_list1 = [] #用于存储牌的花色 user_list2 = [] #用于存储牌的数字 global list4 #声明调用外部全局变量 for i in list4: user_list1.append(list(i.keys())) for j in i: user_list1.append(list(i.values())) user_list2.append(user_list1[1]) #将遍历后的数字添加进user_list2中 user_list2.append(user_list1[3]) user_list2.append(user_list1[5]) user_list2 = [int(x) for item in user_list2 for x in item] #合并列表 user_list2.sort() #列表排序 if user_list2[0] == user_list1[1] == user_list1[2]: #判断三张数字是否相同 num = user_list1[1][0] * 100000 + zhadan elif user_list1[0] == user_list1[2] == user_list1[4] and user_list2[2] - user_list2[1] == user_list2[1] - \ user_list2[0] == 1: #判断三张花色是否相同且连号 num = user_list2[1] * 10000 + shunjin elif user_list2[2] - user_list2[1] == user_list2[1] - user_list2[0] == 1: #判断是否连号 num = user_list2[1] * 1000 + shunzi elif user_list2[0] == user_list2[1] or user_list2[1] == user_list2[2] or user_list2[2] == user_list2[0]: #判断是否有两个一样的数字 if user_list2[0] == user_list2[1]: num = user_list2[0] * 100 + duizi if user_list2[0] == user_list2[2]: num = user_list2[2] * 100 + duizi if user_list2[2] == user_list2[1]: num = user_list2[1] * 100 + duizi elif user_list2[0] != user_list2[1] != user_list2[2]: #最后一种可能,单张 num = user_list2[2] * 10 + user_list2[1] + danzhang return num #返回计算后的分值 # 定义玩家牌型的底分 zhadan = 100 shunjin = 80 shunzi = 60 duizi = 40 danzhang = 20 gamer = [] #定义新列表,存放玩家数量 gamers = int(input('请输入玩家数量(只能2 - 9名):')) if gamers >= 2 and gamers <= 9: #判断用户输入的人数是否在规定范围内 for i in range(gamers): # 玩家数量由用户定义,代表整体循环的次数 list4 = [] # 用于存储每名玩家随机得到的三张牌 for j in range(3): sun = random.randint(1, len(puke()) - 1) # 以随机数为扑克整体的下标进行查找对应的牌 list4.append(puke()[sun]) # 添加进列表 puke().remove(puke()[sun]) # 把已经发出去的牌在扑克牌整体中进行删除 print(f'{i + 1}号玩家的底牌:{list4}') if i == 0: user_1 = func(0) gamer.append(user_1) elif i == 1: user_2 = func(0) gamer.append(user_2) elif i == 2: user_3 = func(0) gamer.append(user_3) elif i == 3: user_4 = func(0) gamer.append(user_4) elif i == 4: user_5 = func(0) gamer.append(user_5) elif i == 5: user_6 = func(0) gamer.append(user_6) elif i == 6: user_7 = func(0) gamer.append(user_7) elif i == 7: user_8 = func(0) gamer.append(user_8) elif i == 8: user_9 = func(0) gamer.append(user_9) else: print('你输入的人数不合理,请重新输入。') old_grade = [] #定义一个新列表,用于存放以玩家排序的分数 new_grade = [] #定义一个新列表,用于存放以大小排序后的分数 for i in gamer: #遍历玩家分数列表 old_grade.append(i) new_grade.extend(old_grade) old_grade.sort(reverse=True) #降序排列后的分数列表 user = 1 for j in new_grade: #遍历玩家顺序的列表 if j == old_grade[0]: print(f'{user}号玩家获胜,得分:{old_grade[0]}') #最终赢家的分数没有实际意义,仅为了判断最大值 else: user += 1
补充:示例2
一、Poker 类(扑克牌)
Card = collections.namedtuple('Card', ['rank', 'suit']) class Poker(MutableSequence): # 扑克牌的相关定义 ranks = [str(n) for n in range(2, 11)] + list('JQKA') suits = 'spades hearts diamonds clubs'.split() # 黑桃,红桃,方块,梅花 suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)#黑桃最大,红桃次之,方块再次之,梅花最小 def __init__(self): self._cards = [Card(rank, suit) for rank in self.ranks for suit in self.suits] def __len__(self): return len(self._cards) def __getitem__(self, position): # 仅仅实现了__getitem__方法,该对象就变成可迭代的 return self._cards[position] def __setitem__(self, position, value): self._cards[position] = value def __delitem__(self, position): del self._cards[position] def insert(self, position, value): self._cards[position] = value
一副扑克牌有 54 张牌,其中 52 张是正牌,另2张是副牌(大王和小王)。本程序中未涉及到大小王。52 张正牌又均分为 13 张一组,并以黑桃、红桃、梅花、方块四种花色表示各组,每组花色的牌包括从 2-10 以及 J、Q、K、A 标示的 13 张牌。
二、Player 类(玩家)
Own_Poker = collections.namedtuple('Own_Poker', ['id', 'rank', 'suit', 'score']) class Player(): ''' 牌型 豹子:三张同样大小的牌。 顺金:花色相同的三张连牌。 金花:三张花色相同的牌。 顺子:三张花色不全相同的连牌。 对子:三张牌中有两张同样大小的牌。 单张:除以上牌型的牌。 ''' def __init__(self, id, poker): self.id = id self.poker = poker #一副扑克牌 self.pokers = [] #玩家手中的牌 self.type = 0 # 每个人初始都假定为三张毫无关系的牌,也就是扑克牌赢法中的“单张” def set_card_score(self, card): ''' 按照点数判定扑克牌的大小 :param card:扑克牌卡片 :return:扑克牌点数大小 ''' rank_value = Poker.ranks.index(card.rank) suit_values = Poker.suit_values return rank_value * len(suit_values) + suit_values[card.suit] def sort_card_index(self, rank_index_list): ''' 通过值减下标的方式分组,如果三个值连续则被分配到同一个g中 比如说ll=[3,4,5,7,8],分组时,enumerate(ll)=[(0,3),(1,4),(2,5),(3,7),(4,8)],fun函数值减下标,结果一样的,就归为一组 在本程序中,如果是三张连续的扑克牌,则应该是同一个g中,此时返回为Ture,否则为False :param rank_index_list: :return: ''' fun = lambda x: x[1] - x[0] for k, g in groupby(enumerate(rank_index_list), fun): # 返回一个产生按照fun进行分组后的值集合的迭代器. if len([v for i, v in g]) == 3: return True return False def judge_type(self): ''' 玩家随机发完三张牌后,根据扑克牌玩法进行区分,对手中的牌进行判别属于哪种类型 :return: ''' suit_list = [] rank_list = [] score_list = [] for poker in self.pokers: suit_list.append(poker.suit) rank_list.append(poker.rank) score_list.append(poker.score) rank_index_list = [] # 扑克牌卡片在Poker中rank中的index for rank in rank_list: index = self.poker.ranks.index(rank) rank_index_list.append(index) if len(set(rank_list)) == 1: self.type = 5 # 豹子 elif len(set(suit_list)) == 1: if self.sort_card_index(rank_index_list): self.type = 4 # 顺金 else: self.type = 3 # 金花 elif self.sort_card_index(rank_index_list): self.type = 2 # 顺子 elif len(set(rank_list)) == 2: self.type = 1 # 对子 def play(self): self.judge_type()
每位玩家都有一个名称,用同一副扑克牌,炸金花游戏要求每人手中有三张牌,根据手中的牌,程序初步判断属于哪种牌型,用于后续游戏取胜机制做判断。
三、Winner 类(游戏取胜机制)
class Winner(): def __init__(self, player1, player2): self.player1 = player1 self.player2 = player2 def get_max_card(self, player): ''' 筛选出三张牌中最大的牌,这里返回的是在ranks中的index :param player: :return: ''' ranks = Poker.ranks rank_index_list = [] # 扑克牌卡片在Poker中rank中的index for poker in player.pokers: index = ranks.index(poker.rank) rank_index_list.append(index) return max(rank_index_list) def get_card_suit(self, player): ''' 返回扑克牌花色大小 :param player: :return: ''' suit_values = Poker.suit_values suit = player.pokers[0].suit return suit_values[suit] def get_card_value(self, player): ''' 当牌型是对子的时候,经过匹配找出是对子的牌和单个的牌,这里返回的是牌的index,便于比较大小 :param player: :return: ''' ranks = Poker.ranks rank_index_dict = {} # 扑克牌卡片在Poker中rank中的index repeat_rank_value = 0 # 成对的两张扑克牌的大小 single_rank_value = 0 # 单个的扑克牌的大小 for poker in player.pokers: index = ranks.index(poker.rank) if index in rank_index_dict: rank_index_dict[index] += 1 else: rank_index_dict[index] = 1 rank_index_dict = sorted(rank_index_dict.items(), key=lambda d: d[1], reverse=True) n = 0 for key in rank_index_dict: if n == 0: repeat_rank_value = key else: single_rank_value = key n += 1 return repeat_rank_value, single_rank_value def get_player_score(self, player): ''' 当牌型为单牌时,计算手中的牌相加后的值大小 :param player: :return: ''' ranks = Poker.ranks score = 0 for poker in player.pokers: index = ranks.index(poker.rank) # 扑克牌卡片在Poker中rank中的index score += index return score def get_winner(self): player1, player2 = self.player1, self.player2 # 先比较玩家手中的牌型,大的胜出,玩牌的规则暂时不涉及到牌色,如有修改可以在此基础上调整 # 豹子> 顺金 > 金花 > 顺子 > 对子 > 单张 if player1.type > player2.type: return player1 elif player1.type < player2.type: return player2 else: # 当玩家双方手中的牌型一致时,根据赢法一一判断 if player1.type == 5 or player1.type == 4 or player1.type == 2: # 豹子、顺金、顺子 规则说明:按照比点 if self.get_max_card(player1) > self.get_max_card(player2): return player1 else: return player2 elif player1.type == 1: # 对子 规则说明:先比较相同两张的值的大小,谁大谁胜出;如果对子相同,再比较单个 repeat_rank_value1, single_rank_value1 = self.get_card_value(player1) repeat_rank_value2, single_rank_value2 = self.get_card_value(player1) if repeat_rank_value1 > repeat_rank_value2: return player1 elif repeat_rank_value1 < repeat_rank_value2: return player2 else: if single_rank_value1 > single_rank_value2: return player1 elif single_rank_value1 < single_rank_value2: return player2 else: return None # 平局,大家手上的牌一样大 else: # 单牌,金花 规则:比较所有牌的点数大小,不区分牌色 if self.get_player_score(player1) > self.get_player_score(player2): return player1 elif self.get_player_score(player1) < self.get_player_score(player2): return player2 else: return None
由于不是很清楚炸金花的游戏规则,这里我们采用的是最简单的游戏规则。
牌型 豹子:三张同样大小的牌。顺金:花色相同的三张连牌。金花:三张花色相同的牌。 顺子:三张花色不全相同的连牌。 对子:三张牌中有两张同样大小的牌。单张:除以上牌型的牌。
玩法比较简单,豹子> 顺金 > 金花 > 顺子 > 对子 > 单张,当牌型不一致的话,谁牌型大谁胜出;当牌型一致的时候,又分为三种情况,一是豹子、顺金、顺子,比较玩家手中牌的最大值,谁拥有最大牌面值谁胜出;二是对子,比较玩家手中对子的牌面大小,如果相同再另行比较;三是金花、单张,比较玩家手中所有牌面大小之和。
除了上述三个对象类外,还需要一个发牌者(荷官)来主持洗牌和发牌。
def compare_card(card1, card2): ''' 比较两种扑克牌是否相同 :param card1: :param card2: :return: 相同返回为True,否则为False ''' if card1.rank == card2.rank and card1.suit == card2.suit: return True return False def dutch_official_work(poker, player1, player2): ''' 发牌人(荷官)给两位玩家轮替发牌,发出去的牌都需要从这副扑克牌中剔除出去 :param poker: 那一副扑克牌 :param player1:玩家1 :param player2:玩家2 :return:整理后的扑克牌 ''' def distribute_card(player): card = choice(poker) # 发牌 player.pokers.append(Own_Poker(player.id, card.rank, card.suit, player.set_card_score(card))) for i in range(len(poker)): if compare_card(card, poker[i]): poker.__delitem__(i) break shuffle(poker) # 洗牌 for k in range(3): distribute_card(player1) distribute_card(player2) return poker
详细代码可以访问 https://github.com/Acorn2/fluentPyStudy/blob/master/chapter01/Poker_Demo.py
到此这篇关于Python实现炸金花游戏的示例代码的文章就介绍到这了,更多相关Python 炸金花游戏内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Python使用ThreadPoolExecutor一次开启多个线程
通过使用ThreadPoolExecutor,您可以同时开启多个线程,从而提高程序的并发性能,本文就来介绍一下Python使用ThreadPoolExecutor一次开启多个线程,感兴趣的可以了解一下2023-11-11
最新评论