python实现扑克牌比较大小,斗地主的规则

规则详情

  1. 首先可以打出的牌有个子,对子,三带一,顺子(大于或等于五张),炸弹。(不允许出三张牌的,即三个一样的不带一张牌)
  2. 两手牌必须是相同的相同类型的,如个子对个子,对子对对子,顺子对顺子。。。炸弹可以和任何牌相比较,两个王最大。
  3. 这里我们假设输入已经合法化,并且输入的牌已经排好序了,因为我们的重点在于比较两手牌的大小。
  4. 定义J,Q,K,A,2 分别对应11,12,13,14,15,joker和JOKER分别为大王小王,对应数字为16,17。

操作环境

  • 操作系统:windows10
  • python版本:python 3.7
  • 代码编辑器:pycharm 2018.2

大致思路

  1. 定义一个类来对我们的代码进行封装。这个类需要接收两个参数,也就是两手牌的值。两手牌分别使用两个列表存起来。
  2. 对传入手牌的值进行格式化,变成我们能比较的值。
  3. 进行比较,再将大的手牌格式化回去,返回手牌。

具体思路

  1. 定义一个PlayingCard类,接收两手牌,(两手牌得是一个列表).并且对接收的手牌进行格式化,变成可以直接比较的值。
class PlayingCard():# 定义格式化操作的对应值format_playing_card_dict = {'3' : 3,'4' : 4,'5' : 5,'6' : 6,'7' : 7,'8' : 8,'9' : 9,'10' : 10,'J' : 11,'Q' : 12,'K' : 13,'A' : 14,'2' : 15,'joker' : 16,'JOKER' : 17,}def __init__(self,left_card,right_card):self.left_card = self._format_playing_card(left_card)self.right_card = self._format_playing_card(right_card)def _format_playing_card(self,cards):'''对手牌进行格式化,成为能直接比较的值:param cards: 手牌列表:return: 返回格式化好的列表'''for index,card in enumerate(cards):if card not in self.format_playing_card_dict:raise ValueError('请输入合法的牌')cards[index] = self.format_playing_card_dict[card]return cards
  1. 我们将手牌格式化好了,就需要来分析怎样进行比较。因为我们认为输入的手牌是合法的,并且经过排序了的,两者也是可以进行比较的手牌,所以就可能出现以下情况
  • 个子与个子比较
  • 对子与对子比较
  • 三带一与三带一比较
  • 顺子与顺子比较
  • 炸弹与炸弹比较,但不包含王炸
  • 炸弹与其他牌进行比较,不包含王炸
  • 包含王炸的比较

这样看起来我们要分七种情况,那么就要写七个方法了。感觉好像有点多啊,还可不可以少点呢?

答案当然是可以的?

因为传入的手牌都是经过排序好了的,并且合法的。那么个子与个子对子与对子顺子与顺子炸弹与炸弹这些比较我们都可以只比较最小的一张牌就能够判断出大小了,所以我们可以把这些都写在一个方法里面。

那么这样分下来,我们就只有四种情况了啊。

  • 比较列表第一个值(第一张牌)的大小
  • 两个都是三带一的比较
  • 炸弹与其他牌进行比较,不包含王炸
  • 包含王炸的比较

这样分下来就少了一些了啊,完美啊!!!

然后我们就开始编写方法。

① 比较两个列表第一个值(第一张牌)的大小

def _compare_first_value(self):'''只需要比较第一张牌的情况:return: 返回较大的一手牌'''if self.left_card[0] > self.right_card[0]:return self.left_cardelse:return self.right_card

② 两个都是三带一的比较

两个都是三带一的话,想要比较两手牌的大小,那么我们就得获取到三张牌的是哪一个牌,得到他的值,然后再比较就可以了。

这里我们就需要获取手牌中每一张牌重复的个数。考虑到我么可能其他位置也需要获取手牌中每一张牌的重复个数,这里我们就单独定义一个方法,来获取每一张牌重复的个数。

def _get_every_value_repeat_count(self,cards):'''给传入的列表中的每个数计数=> [7,7,7,4] : {7:3,4:1}=> [7,7,7,7] : {7:4}:param cards: 牌的列表:return: 返回一个字典,包含不同的每张牌的个数'''temp_dict = {}for card in cards:if card not in temp_dict:temp_dict[card] = 1else:temp_dict[card] += 1return temp_dict

然后我们比较两个三带一的函数就这样写:

def _compare_three_with_one(self):'''比较两个三带一:return: 返回较大的一手牌'''# 分别调用我们的上面写的得到手牌重复个数的方法,得到一个字典left_cards_dict = self._get_every_value_repeat_count(self.left_card)right_cards_dict = self._get_every_value_repeat_count(self.right_card)left_number = right_number = 0# 分别从返回的字典中得到重复个数为三的值,就是我们三带一的比较对象for key,value in left_cards_dict.items():if value == 3:left_number = keybreakfor key,value in right_cards_dict.items():if value == 3:right_number = keybreakif left_number > right_number:return self.left_cardelse:return self.right_card

③ 炸弹和其他牌的比较,但是不包含王炸

def _compare_bomb_and_others(self):'''炸弹和其他牌的比较:return: 返回较大的一手牌'''if max( self._get_every_value_repeat_count(self.left_card).values() ) == 4:return self.left_cardelse:return self.right_card

果然我们还时会用到self._get_every_value_repeat_count()这个方法.这个方法我们定义的是返回一个字典,我们再调用字典的.values()方法,就能得到所有的值了。

这里说一下max函数的使用方法:得到一个序列中的最大值并返回该值

  • max函数演示
max([2,6,9,4,10,8])     # => 10

④ 包含王炸的比较

def _compare_has_two_joker(self):'''有两个王的比较:return: 返回较大的一手牌'''if self.left_card[0] == 16:return self.left_cardelse:return self.right_card

因为我们传入的手牌是排序好了的,所以我们直接判断第一张牌的值是否为16(也就是小王joker),如果是,那么他就肯定是王炸了,如果不是,那么另外一个肯定是王炸了。因为如果没有王炸我们肯定是不会执行这个函数的。

到这里为止,我们就把所有的比较方法写完了,接下来我们就要判断我们到底该使用哪一种方法了

首先我们可以写一个字典,来存储我们方法的对应表。我们就直接在__init__()函数中添加了。

def __init__(self,left_card,right_card):self.left_card = self._format_playing_card(left_card)self.right_card = self._format_playing_card(right_card)self.function_map = {1: self._compare_first_value,  # 只用比较第一张牌的大小2: self._compare_has_two_joker,  # 有双王的比较3: self._compare_three_with_one,  # 都是三带一的比较4: self._compare_bomb_and_others,  # 一个炸弹和其他牌的比较}

然后我们判断出应该使用哪一种方法之后,就返回相应的值就可以了。

def _judge_compare_method(self):'''判断使用那一中方法比较手牌,:return: 返回相应的key'''left_len = len(self.left_card)right_len = len(self.right_card)# 首先判断两手牌长度相等的情况if left_len == right_len:# 都是单个 只需要比较第一张牌if left_len == 1:return 1# 都有两张牌,有两张情况,都是对子,或者为两个王,但是不可能出现两个人都是两个王elif left_len == 2:# 因为我们的输入默认是已经经过排序了的,所以我们只需要知道第一张牌是否为16,如果是的话,就是双王,有双王的情况if self.left_card[0] == 16 or self.right_card[0] == 16:return 2# 两个对子比较,只需要比较第一张牌的大小else:return 1# 没有牌数等于三的情况,所以就跳过三张牌的情况,分析四张牌的情况。# 这里有三种情况,都是三带一,都是炸弹,一个炸弹一个三带一elif left_len == 4:# 看,这个位置又可以使用我们的`self._get_every_value_repeat_count()`方法了left_max_repeat_count = max( self._get_every_value_repeat_count(self.left_card).values() )right_max_repeat_count = max( self._get_every_value_repeat_count(self.right_card).values() )# 都是三带一或者炸弹情况if left_max_repeat_count == right_max_repeat_count:# 都是三带一的情况if left_max_repeat_count == 3:return 3# 都是炸弹的情况,只需要比较第一张牌else:return 1# 一个三带一,一个炸弹的情况else:return 4# 都是顺子的情况 最少5张牌,最多12张牌,也只需要比较第一张牌elif left_len >= 5 and left_len <= 12:return 1# 处理其他意外情况,应该是不会出现这种情况的else:return None# 两手牌长度不相等的情况 必须得有一个炸弹else:# 有王炸的情况if left_len == 2 or right_len == 2:return 3# 没有王炸的情况,有一个炸弹的情况else:return 4

到了这一步为止,我们对手牌的比较基本上算是完成了,只是还有一点,我们是对传入进来的手牌进行 格式化的,所以我们需要将手牌变回去,在返回回去。

def _show_playing_card(self,cards):'''对格式化之后的手牌改变回去:param cards: 格式化之后的手牌列表:return: 返回改变回去的手牌列表'''keys_list = list(self.format_playing_card_dict.keys())values_list = list(self.format_playing_card_dict.values())for index,card in enumerate(cards):key_index = values_list.index(card)cards[index] = keys_list[key_index]return cards

这里说一下list.index(value)方法。返回列表中传入值得下标,如果不存在这个值,就会抛出ValueError的异常.

  • list.index(value)用法演示
a = [1,2,3,4,5]
print(a.index(4))   # => 3
print(a.index(6))   # 抛出ValueError的异常

好了,到了这一步,我们就将所有的功能函数都写完了,接下来我们个这个类写一个接口函数,然后将我们的结果返回回去。

def compare_two_cards(self):'''比较两副牌的大小,返回较大的一副牌:return:'''# 得到应该使用哪一种方法的可以method_key = self._judge_compare_method()# 通过key拿到对应的函数method = self.function_map[method_key]# 执行函数,得到结果手牌cards = method()# 对手牌进行可视化cards = self._show_playing_card(cards)return cards

好了,我们的代码终于写完了,可以开心的测试我们的代码了

PlayingCard(['4'],['9']).compare_two_cards()    # => ['9']
PlayingCard(['joker'],['JOKER']).compare_two_cards()    # => ['JOKER']
PlayingCard(['2','2'],['J','J']).compare_two_cards()    # => ['2','2']
PlayingCard(['2','2','2','5'],['8','8','8','joker']).compare_two_cards()    # => ['2','2','2','5']
PlayingCard(['2','2','2','9'],['4','4','4','4']).compare_two_cards()    # => ['4','4','4','4']
PlayingCard(['joker','JOKER'],['K','K','K','K']).compare_two_cards()    # => ['joker','JOKER]

python实现比较两手牌的大小--斗地主规则相关推荐

  1. java斗地主比大小_斗地主算法的设计与实现(三)--如何比较两手牌的大小

    本篇主要讲解斗地主中如何比较两手牌的大小. 友情提示:本篇是接着以下两篇文章就讲解的,建议先看看下面这2篇. 牌型比较 火箭最大:炸弹次之:再次是一般牌型(单牌.对牌.三张牌.三带一.单顺.双顺.三顺 ...

  2. 斗地主算法的设计与实现(三)--如何比较两手牌的大小

    本篇主要讲解斗地主中如何比较两手牌的大小. 友情提示:本篇是接着以下两篇文章就讲解的,建议先看看下面这2篇. 斗地主算法的设计与实现--如何判断一手牌的类型(单,对子,三不带,三带一,四代二等) 斗地 ...

  3. python斗地主出牌算法_斗地主之用蚁群算法整理牌型:如何进行牌力估计

    我们在前面讲到过,各牌手的牌力估计就是我们在用蚁群算法构造最优牌型时的启发性知识.启发性知识其实就是我们利用自己的经验对事物做出的判优性评估,或者说就是对事物价值的判断. 原则上,应用蚁群算法需要用到 ...

  4. unity开发 斗地主算法—比较两个手牌的大小

    牌型的定义在http://blog.csdn.net/csdn_cjt/article/details/78593140 第一章 这是第二章 下面是代码 #region isSelectCardCan ...

  5. 实现斗地主牌的大小顺序,实现分发牌的顺序,每个人手中的牌按照大小排序

    //1.准备牌,没有自然顺序, 我们可使用查表法//1.准备规则ArrayList<String> regulation = new ArrayList<>();regulat ...

  6. Python学习笔记之扑克牌比大小

    一.系列缘由   作为一名运维工程师,也一直有一个学习开发的想法,值此之际,不知道博客的下一期目标在哪里,在这思考和犹豫的间隙想着学习和充实一下自己,学习一下python语言,python随着大数据和 ...

  7. 心形尺寸比例图解_标识牌尺寸大小及空间比例关系示意图与人体工程学

    标识牌做多大尺寸最合适,没有一个标准的大小.主要衡量标准就是把标识牌放到特定的空间里,按空间大小来制作.什么样的场合,什么样的人群都要考滤在其中,比如儿童游乐园,主要对象就是儿童.标识牌的大小肯定要比 ...

  8. python猜大小游戏,Python实现的摇骰子猜大小功能小游戏示例

    搜索热词 本文实例讲述了Python实现的摇骰子猜大小功能小游戏.分享给大家供大家参考,具体如下: 最近学习Python的随机数,逻辑判断,循环的用法,就想找一些练习题,比如小游戏猜大小,程序思路如下 ...

  9. JAVA 单张牌出牌逻辑 实现斗地主

    JAVA 单张牌出牌逻辑 实现斗地主 Card类 public class Card {Integer degree;String color;public Card(Integer degree, ...

  10. 在python中创建一个具有特定大小的空列表

    本文翻译自:Create an empty list in python with certain size I want to create an empty list (or whatever i ...

最新文章

  1. (原)Eclipse 字体过小问题
  2. MySQL数据类型和运算符
  3. mysql md5版本校验_通过MD5校验和验证MySQL软件包的完整性
  4. VTK:Utilities之ColorLookupTable
  5. WCF自定义地址路由映射(不用svc文件)
  6. java 正则表达式 提取ip_java正则表达式提取地址中的ip和端口号
  7. os如何处理键盘的所有按键,显示or不显示,显示是如何显示
  8. python in memory_使用 in_memory 工作空间的注意事项
  9. Ranger-Usersync安装
  10. 阅读器关闭时尝试调用 Read 无效
  11. 带宽与虚拟桌面的考虑
  12. linux查看进程占用内存与ps命令
  13. 性能测试oracle瓶颈定位,性能测试难点之瓶颈分析
  14. 国内docker镜像网站
  15. lora终端连接云服务器_开源LoRa网关与服务器
  16. NB-IoT技术发展史漫谈(NB-IoT专栏—拓展篇1)
  17. 微信小程序星星评分代码片段(含半星)
  18. VMware虚拟机中使用usb设备
  19. iQOO Z3、OPPOK9和小米11青春版的区别 哪个好
  20. 智源发布《人工智能的认知神经基础白皮书》,一览“AI×脑科学”前沿

热门文章

  1. 2022茶艺师(初级)考试试题模拟考试平台操作
  2. python中文分词算法_基于Python语言的中文分词技术的研究
  3. 虚拟机vm介绍及虚拟机常见操作
  4. Cheat Engine(CE)-----下载安装及入门
  5. (Android+Qt最小系统设计方案)RK3288核心板设计之软件开发环境搭建(4.0)
  6. java vo层_JAVA3个数据层(pojo,dto,vo)、dao层、services层、controller层解释
  7. logging 详解第三期:Logging 不为人知的二三事
  8. C语言应用(3)——Base64编码/解码
  9. java read dxf xdata_dxf结构解析及读取坐标 | 学步园
  10. MAUI 跨平台应用开发实战