用 Python 打扑克牌——炸金花
写了那么久的博客,始于Python爬虫,目前专于Java学习,终于有了属于自己的小窝,欢迎各位访问我的个人网站,未来我们一起交流进步。
在学习《流畅的Python》一书中,第一节 Python 数据类型讲解的过程中,实现了一副扑克牌,代码实现非常简洁。当看完之后,联想到生活中我们玩过的炸金花,便着手设计了程序,用来实现双人炸金花这种游戏模型。
本程序中主要分为三个对象类,Poker 类(扑克牌),Player 类(玩家),Winner 类(游戏取胜机制)。
一、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.ranksfor 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] = valuedef __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 = idself.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_valuesreturn 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 Truereturn Falsedef 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中的indexfor 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 = player1self.player2 = player2def get_max_card(self, player):'''筛选出三张牌中最大的牌,这里返回的是在ranks中的index:param player::return:'''ranks = Poker.ranksrank_index_list = [] # 扑克牌卡片在Poker中rank中的indexfor 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_valuessuit = player.pokers[0].suitreturn suit_values[suit]def get_card_value(self, player):'''当牌型是对子的时候,经过匹配找出是对子的牌和单个的牌,这里返回的是牌的index,便于比较大小:param player::return:'''ranks = Poker.ranksrank_index_dict = {} # 扑克牌卡片在Poker中rank中的indexrepeat_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] += 1else:rank_index_dict[index] = 1rank_index_dict = sorted(rank_index_dict.items(), key=lambda d: d[1], reverse=True)n = 0for key in rank_index_dict:if n == 0:repeat_rank_value = keyelse:single_rank_value = keyn += 1return repeat_rank_value, single_rank_valuedef get_player_score(self, player):'''当牌型为单牌时,计算手中的牌相加后的值大小:param player::return:'''ranks = Poker.ranksscore = 0for poker in player.pokers:index = ranks.index(poker.rank) # 扑克牌卡片在Poker中rank中的indexscore += indexreturn scoredef get_winner(self):player1, player2 = self.player1, self.player2# 先比较玩家手中的牌型,大的胜出,玩牌的规则暂时不涉及到牌色,如有修改可以在此基础上调整# 豹子> 顺金 > 金花 > 顺子 > 对子 > 单张if player1.type > player2.type:return player1elif player1.type < player2.type:return player2else: # 当玩家双方手中的牌型一致时,根据赢法一一判断if player1.type == 5 or player1.type == 4 or player1.type == 2: # 豹子、顺金、顺子 规则说明:按照比点if self.get_max_card(player1) > self.get_max_card(player2):return player1else:return player2elif 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 player1elif repeat_rank_value1 < repeat_rank_value2:return player2else:if single_rank_value1 > single_rank_value2:return player1elif single_rank_value1 < single_rank_value2:return player2else:return None # 平局,大家手上的牌一样大else: # 单牌,金花 规则:比较所有牌的点数大小,不区分牌色if self.get_player_score(player1) > self.get_player_score(player2):return player1elif self.get_player_score(player1) < self.get_player_score(player2):return player2else: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 Truereturn Falsedef 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)breakshuffle(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 来实现一个类似炸金花的扑克牌小游戏,先来看一下基本的游戏规则. 炸(诈)金花又叫三张牌,是在全国广泛流传的一种民间多人纸牌游戏.游戏 ...
- 熬了三个大夜利用Python开发一个炸金花小游戏,注意别玩上瘾了~~(附完整源码)
大家好,我是你们的好朋友王老师~ 众所周知扑克牌可谓是居家旅行.桌面交友的必备道具,今天我们用 Python 来实现一个类似炸金花的扑克牌小游戏,先来看一下基本的游戏规则. 炸(诈)金花又叫三张牌, ...
- Python开发一个炸金花小游戏,注意别玩上瘾了
众所周知扑克牌可谓是居家旅行.桌面交友的必备道具,今天我们用 Python 来实现一个类似炸金花的扑克牌小游戏,先来看一下基本的游戏规则. 炸(诈)金花又叫三张牌,是在全国广泛流传的一种民间多人纸牌 ...
- python开发的炸金花小游戏来啦,从此不再无聊~
哈喽~大家好,我是恰恰!大家今天应该都已经开工了,很多同学过年的时候都是在牌桌上度过的吧哈哈,所以今天给大家带来一个用Python开发的扎金花的小游戏,又可以学习又可以玩,趣味性学习没错了!快来看看吧 ...
- 用python开发一个炸金花小游戏,注意别玩上瘾了~~
众所周知扑克牌可谓是居家旅行.桌面交友的必备道具,今天我们用 Python 来实现一个类似炸金花的扑克牌小游戏,先来看一下基本的游戏规则. 炸(诈)金花又叫三张牌,是在全国广泛流传的一种民间多人纸牌 ...
- 用python开发一个炸金花小游戏,注意别玩上瘾了~~(附完整源码)
大家好,我是辰哥~ 众所周知扑克牌可谓是居家旅行.桌面交友的必备道具,今天我们用 Python 来实现一个类似炸金花的扑克牌小游戏,先来看一下基本的游戏规则. 炸(诈)金花又叫三张牌,是在全国广泛流 ...
- Python写的炸金花程序(含有特殊牌,可供2-17人重复玩耍)
下面附上运行示例 输入1可再来一局 输入2可退出程序 下面附上源码,游戏规则在源码最后 import random#生成一副扑克牌,除去大小王 poker1=[2,3,4,5,6,7,8,9,10, ...
- Python解炸金花问题
Python解炸金花问题 炸金花小游戏 游戏规则: 整体代码 炸金花小游戏 -要求: 编写炸金花游戏程序 自己写一个程序,实现发牌.比大小判断输赢. 游戏规则: 一付扑克牌,去掉大小王,每个玩家发3张 ...
- 用Python写炸金花代码,学习python语言精品案例
以下代码对于练习python相关的条件循环语句.自定义函数及函数调用.列表.字典.变量运算.基本逻辑等的练习很有帮助,特别是如何使用python语言解决实际问题的思路,且具有一定趣味性,对于Pytho ...
最新文章
- 2021年大数据Spark(三十九):SparkStreaming实战案例四 窗口函数
- android原生跳转到外网
- 清理恶意插件提高上网速度
- 纪中2018暑假培训day3提高a组改题记录(混有部分b组)
- js文章QQ空间分享
- 在linux中which命令,Linux 中 which 命令怎么用?
- 因为apple无法检查其是否包含恶意软件_新Linux恶意脚本——清理其他恶意软件后再感染...
- H5页面适配iOS、Android和微信
- 兼容IE和FF:获取Referer的JS和PHP方法 及 PHP利用curl伪造IP和来路
- 3.8 RIPv2的认证机制
- Android蓝牙电话(SCO)和蓝牙音乐(A2DP)总结(四)
- 编译出错:self-encoder.context-me_method = ME_UMH;
- 【优化算法】孪生支持向量机(TWSVM)【含Matlab源码 1257期】
- 算法的时间复杂度与空间复杂度
- resnet34\resnet101网络结构图
- WPS 表格中单元格文字后插入公式
- 模拟停车场管理系统(栈和队列的应用)
- 我们都是穷人甲乙丙丁
- 2023款16英寸苹果MacBook Pro续航实测
- 图片 bmp 格式详解