• 斗地主发牌程序的 Python 实现与解析


    目录

    一、扑克牌类的设计

    (一)PokerCard 类的属性

    (二)权重计算方法

    (三)字符串表示方法

    (四)比较大小方法

    二、牌堆的生成

    generate_deck 函数

    三、洗牌操作

    shuffle_deck 函数

    四、发牌操作

    deal_cards 函数

    五、斗地主发牌程序的主流程

    display_cards 函数

    六、代码

    七、总结


            斗地主是一款深受大众喜爱的纸牌游戏,在开发相关游戏程序或者模拟斗地主场景时,发牌程序是其中的关键部分。本文将详细介绍如何使用 Python 实现一个斗地主发牌程序,包括扑克牌类的设计、牌堆的生成、洗牌以及发牌等操作,并深入解析代码的实现原理和逻辑。

    一、扑克牌类的设计

    (一)PokerCard 类的属性

            在我们的程序中,定义了PokerCard类来表示一张扑克牌。它有两个重要的属性:point(点数)和color(花色)。点数可以是345等常规数字,以及JQKA2,还有特殊的Joker(代表大小王)。花色则包括(黑桃)、(红桃)、(方片)、(梅花),对于大小王可以用特殊的标识比如来区分。

    1. def __init__(self, point, color):
    2. """
    3. 扑克牌类的构造函数。
    4. :param point: 扑克牌的点数。
    5. :param color: 扑克牌的花色。
    6. """
    7. self.point = point
    8. self.color = color
    9. # 自定义权重,用于比较大小
    10. self.weight = self.get_weight()

    (二)权重计算方法

            为了能够方便地比较扑克牌的大小,我们为每张牌计算了一个权重值。在get_weight方法中,我们首先定义了点数和花色对应的权重字典。对于常规的牌,权重是点数权重乘以10再加上花色权重。例如,一张红桃55的点数权重是5,红桃的花色权重是3,那么它的权重就是5 * 10 + 3 = 53。对于大小王,我们赋予了一个较大的值(这里是999)来确保它们在比较大小时处于最大的位置。

    1. def get_weight(self):
    2. """
    3. 计算扑克牌的权重,用于比较大小。
    4. :return: 扑克牌的权重值。
    5. """
    6. points = {'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}
    7. colors = {'♠': 4, '♥': 3, '♦': 2, '♣': 1}
    8. if self.point == 'Joker':
    9. return 999 # 可以根据需要设置一个较大的值表示大小王的权重
    10. else:
    11. return points[self.point] * 10 + colors[self.color]

    (三)字符串表示方法

       __str____repr__方法用于返回扑克牌的字符串表示形式。这两个方法使得我们可以方便地将扑克牌对象转换为可以打印输出的字符串,例如5♥这样的形式,方便在程序中展示手牌等信息。

    1. def __str__(self):
    2. """
    3. 返回扑克牌的字符串表示。
    4. :return: 扑克牌的字符串形式。
    5. """
    6. return f'{self.point}{self.color}'
    7. def __repr__(self):
    8. """
    9. 返回扑克牌在交互环境中的表示形式,与__str__方法类似。
    10. :return: 扑克牌的字符串形式。
    11. """
    12. return f'{self.point}{self.color}'

    (四)比较大小方法

       __lt__方法定义了扑克牌之间的小于比较逻辑。通过比较两张牌的权重值,我们可以轻松地判断哪张牌更小。这样在对手牌进行排序时,就可以按照我们设定的规则,即先按点数从小到大,点数相同再按花色(黑桃 > 红桃 > 方片 > 梅花)的顺序进行排列。

    1. def __lt__(self, other):
    2. """
    3. 定义小于比较方法,用于扑克牌的排序。
    4. :param other: 另一个扑克牌对象。
    5. :return: 如果当前扑克牌权重小于另一个,则返回 True,否则返回 False。
    6. """
    7. return self.weight < other.weight

    二、牌堆的生成

    generate_deck 函数

       generate_deck函数用于生成一副完整的扑克牌。我们通过嵌套的循环遍历所有的点数和花色组合,创建PokerCard对象并添加到牌堆列表中。最后,再将大小王也添加到牌堆中,这样就得到了包含54张牌的牌堆。这种生成方式简单且直观,清晰地构建了游戏所需的基本数据结构。

    1. def generate_deck():
    2. """
    3. 生成一副扑克牌。
    4. :return: 包含 54 张扑克牌的列表。
    5. """
    6. points = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2']
    7. colors = ['♠', '♥', '♦', '♣']
    8. deck = [PokerCard(point, color) for point in points for color in colors]
    9. deck += [PokerCard('Joker', '大'), PokerCard('Joker', '小')]
    10. return deck

    三、洗牌操作

    shuffle_deck 函数

       shuffle_deck函数实现了对牌堆的洗牌功能。这里我们使用了 Python 的random模块中的shuffle函数。它会随机地打乱输入的列表元素顺序,从而实现了对牌堆中扑克牌的随机洗牌,使得每一局游戏的发牌都具有随机性。

    1. def shuffle_deck(deck):
    2. """
    3. 随机洗牌。
    4. :param deck: 扑克牌列表。
    5. :return: 洗牌后的扑克牌列表。
    6. """
    7. import random
    8. random.shuffle(deck)
    9. return deck

    四、发牌操作

    deal_cards 函数

       deal_cards函数负责将洗好的牌发给三个玩家。我们使用了一个字典players来存储每个玩家的手牌,其中键是玩家的名字,值是一个列表,用于存放该玩家的手牌。通过两层循环,外层循环控制发牌的轮数(这里是17轮,因为每个玩家先发17张牌),内层循环遍历每个玩家,每次从牌堆中取出一张牌并添加到当前玩家的手牌列表中。最后返回包含三个玩家手牌信息的字典。

    1. def deal_cards(deck):
    2. """
    3. 发牌给三个玩家。
    4. :param deck: 扑克牌列表。
    5. :return: 包含三个玩家手牌的字典。
    6. """
    7. players = {'江煜煋': [], '周自横': [], '易相逢': []}
    8. for _ in range(17):
    9. for player in players:
    10. players[player].append(deck.pop())
    11. return players

    五、斗地主发牌程序的主流程

    display_cards 函数

    display_cards函数是整个斗地主发牌程序的核心流程控制函数。

    1. 欢迎信息与玩家输入
      首先,它打印出欢迎进入斗地主游戏的信息,并遍历玩家列表,输出每个玩家的输入提示。这里我们使用了一个预设的玩家列表['江煜煋', '周自横', '易相逢'],在实际应用中,可以根据用户输入来动态获取玩家名字。
    2. 洗牌与发牌过程展示
      接着,它调用generate_deck函数生成牌堆,然后使用shuffle_deck函数洗牌,并输出相应的提示信息。之后调用deal_cards函数进行发牌,并在发牌完成后,遍历玩家和他们的手牌,对手牌进行排序并将排序后的手牌以字符串形式输出。这里使用了sorted函数对手牌列表进行排序,排序依据是我们在PokerCard类中定义的__lt__比较方法。
    3. 地主选择与地主牌处理
      然后,程序会询问哪个玩家叫地主,并获取用户输入。根据用户输入的地主玩家名字,获取该玩家的手牌,并从剩余的牌堆中取出最后三张作为地主额外的牌(地主牌)。将地主牌和地主原有的手牌合并后重新排序,并输出地主的手牌信息。最后,遍历其他玩家,输出他们的手牌信息,完成整个发牌和地主确定的流程展示。

    1. def display_cards(players):
    2. """
    3. 斗地主发牌程序的主要流程。
    4. :param players: 玩家列表。
    5. """
    6. print("********** 欢迎进入XXX斗地主 **********")
    7. for player in players:
    8. print(f"请输入玩家姓名:{player}")
    9. print("洗牌中...")
    10. deck = generate_deck()
    11. shuffled_deck = shuffle_deck(deck)
    12. print("洗牌完成!")
    13. print("发牌中...")
    14. dealt_players = deal_cards(shuffled_deck)
    15. print("发牌完成!")
    16. for player, cards in dealt_players.items():
    17. sorted_cards = sorted(cards)
    18. card_str = ", ".join(str(card) for card in sorted_cards)
    19. print(f"{player}: {card_str}")
    20. landlord = input("谁叫地主? ")
    21. landlord_cards = dealt_players[landlord]
    22. landlord_extra_cards = shuffled_deck[-3:]
    23. print(f"地主张牌:{', '.join(str(card) for card in landlord_extra_cards)}")
    24. landlord_cards += landlord_extra_cards
    25. sorted_landlord_cards = sorted(landlord_cards)
    26. landlord_card_str = ", ".join(str(card) for card in sorted_landlord_cards)
    27. print(f"{landlord}(地主): {landlord_card_str}")
    28. for player, cards in dealt_players.items():
    29. if player == landlord:
    30. continue
    31. sorted_cards = sorted(cards)
    32. card_str = ", ".join(str(card) for card in sorted_cards)
    33. print(f"{player}: {card_str}")

    六、代码

    1. class PokerCard:
    2. def __init__(self, point, color):
    3. """
    4. 扑克牌类的构造函数。
    5. :param point: 扑克牌的点数。
    6. :param color: 扑克牌的花色。
    7. """
    8. self.point = point
    9. self.color = color
    10. # 自定义权重,用于比较大小
    11. self.weight = self.get_weight()
    12. def get_weight(self):
    13. """
    14. 计算扑克牌的权重,用于比较大小。
    15. :return: 扑克牌的权重值。
    16. """
    17. points = {'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}
    18. colors = {'♠': 4, '♥': 3, '♦': 2, '♣': 1}
    19. if self.point == 'Joker':
    20. return 999 # 可以根据需要设置一个较大的值表示大小王的权重
    21. else:
    22. return points[self.point] * 10 + colors[self.color]
    23. def __str__(self):
    24. """
    25. 返回扑克牌的字符串表示。
    26. :return: 扑克牌的字符串形式。
    27. """
    28. return f'{self.point}{self.color}'
    29. def __repr__(self):
    30. """
    31. 返回扑克牌在交互环境中的表示形式,与__str__方法类似。
    32. :return: 扑克牌的字符串形式。
    33. """
    34. return f'{self.point}{self.color}'
    35. def __lt__(self, other):
    36. """
    37. 定义小于比较方法,用于扑克牌的排序。
    38. :param other: 另一个扑克牌对象。
    39. :return: 如果当前扑克牌权重小于另一个,则返回 True,否则返回 False。
    40. """
    41. return self.weight < other.weight
    42. def generate_deck():
    43. """
    44. 生成一副扑克牌。
    45. :return: 包含 54 张扑克牌的列表。
    46. """
    47. points = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2']
    48. colors = ['♠', '♥', '♦', '♣']
    49. deck = [PokerCard(point, color) for point in points for color in colors]
    50. deck += [PokerCard('Joker', '大'), PokerCard('Joker', '小')]
    51. return deck
    52. def shuffle_deck(deck):
    53. """
    54. 随机洗牌。
    55. :param deck: 扑克牌列表。
    56. :return: 洗牌后的扑克牌列表。
    57. """
    58. import random
    59. random.shuffle(deck)
    60. return deck
    61. def deal_cards(deck):
    62. """
    63. 发牌给三个玩家。
    64. :param deck: 扑克牌列表。
    65. :return: 包含三个玩家手牌的字典。
    66. """
    67. players = {'玩家A': [], '玩家B': [], '玩家C': []}
    68. for _ in range(17):
    69. for player in players:
    70. players[player].append(deck.pop())
    71. return players
    72. def display_cards(players):
    73. """
    74. 斗地主发牌程序的主要流程。
    75. :param players: 玩家列表。
    76. """
    77. print("********** 欢迎进入XXX斗地主 **********")
    78. for player in players:
    79. print(f"请输入玩家姓名:{player}")
    80. print("洗牌中...")
    81. deck = generate_deck()
    82. shuffled_deck = shuffle_deck(deck)
    83. print("洗牌完成!")
    84. print("发牌中...")
    85. dealt_players = deal_cards(shuffled_deck)
    86. print("发牌完成!")
    87. for player, cards in dealt_players.items():
    88. sorted_cards = sorted(cards)
    89. card_str = ", ".join(str(card) for card in sorted_cards)
    90. print(f"{player}: {card_str}")
    91. landlord = input("谁叫地主? ")
    92. landlord_cards = dealt_players[landlord]
    93. landlord_extra_cards = shuffled_deck[-3:]
    94. print(f"地主张牌:{', '.join(str(card) for card in landlord_extra_cards)}")
    95. landlord_cards += landlord_extra_cards
    96. sorted_landlord_cards = sorted(landlord_cards)
    97. landlord_card_str = ", ".join(str(card) for card in sorted_landlord_cards)
    98. print(f"{landlord}(地主): {landlord_card_str}")
    99. for player, cards in dealt_players.items():
    100. if player == landlord:
    101. continue
    102. sorted_cards = sorted(cards)
    103. card_str = ", ".join(str(card) for card in sorted_cards)
    104. print(f"{player}: {card_str}")
    105. display_cards(['玩家A', '玩家B', '玩家C'])

    七、总结

            本文详细介绍了一个使用 Python 实现的斗地主发牌程序。通过设计PokerCard类来表示扑克牌,实现了扑克牌的属性、权重计算、字符串表示和大小比较等功能。利用generate_deckshuffle_deckdeal_cards等函数完成了牌堆的生成、洗牌和发牌操作。display_cards函数则整合了整个发牌流程,包括欢迎信息、玩家输入、洗牌发牌展示以及地主相关的处理。希望本文能为读者在开发纸牌游戏相关程序时提供有益的参考和启发,进一步探索和完善斗地主游戏程序以及其他类似的纸牌游戏程序的开发。

  • 相关阅读:
    SpringCloud gateway自定义请求的 httpClient
    华为Mate 60系列发售,北斗卫星通信技术进一步深入大众消费市场
    CMS垃圾收集器与三色标记算法详解
    Apollo 应用与源码分析:CyberRT-话题通信
    Day 89
    天天项目管理软件
    c++ 信奥编程 1129:统计数字字符个数
    qsort(冒泡排序)
    文档、视频、图片上传(点击、拖拽、批量导入)要‍‍‍‍怎么实现?!
    2022年java开发面试题整理合集
  • 原文地址:https://blog.csdn.net/weixin_64726356/article/details/143398894