目录
斗地主是一款深受大众喜爱的纸牌游戏,在开发相关游戏程序或者模拟斗地主场景时,发牌程序是其中的关键部分。本文将详细介绍如何使用 Python 实现一个斗地主发牌程序,包括扑克牌类的设计、牌堆的生成、洗牌以及发牌等操作,并深入解析代码的实现原理和逻辑。
在我们的程序中,定义了PokerCard
类来表示一张扑克牌。它有两个重要的属性:point
(点数)和color
(花色)。点数可以是3
、4
、5
等常规数字,以及J
、Q
、K
、A
、2
,还有特殊的Joker
(代表大小王)。花色则包括♠
(黑桃)、♥
(红桃)、♦
(方片)、♣
(梅花),对于大小王可以用特殊的标识比如大
和小
来区分。
- def __init__(self, point, color):
- """
- 扑克牌类的构造函数。
- :param point: 扑克牌的点数。
- :param color: 扑克牌的花色。
- """
- self.point = point
- self.color = color
- # 自定义权重,用于比较大小
- self.weight = self.get_weight()
为了能够方便地比较扑克牌的大小,我们为每张牌计算了一个权重值。在get_weight
方法中,我们首先定义了点数和花色对应的权重字典。对于常规的牌,权重是点数权重乘以10
再加上花色权重。例如,一张红桃5
,5
的点数权重是5
,红桃的花色权重是3
,那么它的权重就是5 * 10 + 3 = 53
。对于大小王,我们赋予了一个较大的值(这里是999
)来确保它们在比较大小时处于最大的位置。
- def get_weight(self):
- """
- 计算扑克牌的权重,用于比较大小。
- :return: 扑克牌的权重值。
- """
- 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}
- colors = {'♠': 4, '♥': 3, '♦': 2, '♣': 1}
- if self.point == 'Joker':
- return 999 # 可以根据需要设置一个较大的值表示大小王的权重
- else:
- return points[self.point] * 10 + colors[self.color]
__str__
和__repr__
方法用于返回扑克牌的字符串表示形式。这两个方法使得我们可以方便地将扑克牌对象转换为可以打印输出的字符串,例如5♥
这样的形式,方便在程序中展示手牌等信息。
- def __str__(self):
- """
- 返回扑克牌的字符串表示。
- :return: 扑克牌的字符串形式。
- """
- return f'{self.point}{self.color}'
-
- def __repr__(self):
- """
- 返回扑克牌在交互环境中的表示形式,与__str__方法类似。
- :return: 扑克牌的字符串形式。
- """
- return f'{self.point}{self.color}'
__lt__
方法定义了扑克牌之间的小于比较逻辑。通过比较两张牌的权重值,我们可以轻松地判断哪张牌更小。这样在对手牌进行排序时,就可以按照我们设定的规则,即先按点数从小到大,点数相同再按花色(黑桃 > 红桃 > 方片 > 梅花)的顺序进行排列。
- def __lt__(self, other):
- """
- 定义小于比较方法,用于扑克牌的排序。
- :param other: 另一个扑克牌对象。
- :return: 如果当前扑克牌权重小于另一个,则返回 True,否则返回 False。
- """
- return self.weight < other.weight
generate_deck
函数用于生成一副完整的扑克牌。我们通过嵌套的循环遍历所有的点数和花色组合,创建PokerCard
对象并添加到牌堆列表中。最后,再将大小王也添加到牌堆中,这样就得到了包含54
张牌的牌堆。这种生成方式简单且直观,清晰地构建了游戏所需的基本数据结构。
- def generate_deck():
- """
- 生成一副扑克牌。
- :return: 包含 54 张扑克牌的列表。
- """
- points = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2']
- colors = ['♠', '♥', '♦', '♣']
- deck = [PokerCard(point, color) for point in points for color in colors]
- deck += [PokerCard('Joker', '大'), PokerCard('Joker', '小')]
- return deck
shuffle_deck
函数实现了对牌堆的洗牌功能。这里我们使用了 Python 的random
模块中的shuffle
函数。它会随机地打乱输入的列表元素顺序,从而实现了对牌堆中扑克牌的随机洗牌,使得每一局游戏的发牌都具有随机性。
- def shuffle_deck(deck):
- """
- 随机洗牌。
- :param deck: 扑克牌列表。
- :return: 洗牌后的扑克牌列表。
- """
- import random
- random.shuffle(deck)
- return deck
deal_cards
函数负责将洗好的牌发给三个玩家。我们使用了一个字典players
来存储每个玩家的手牌,其中键是玩家的名字,值是一个列表,用于存放该玩家的手牌。通过两层循环,外层循环控制发牌的轮数(这里是17
轮,因为每个玩家先发17
张牌),内层循环遍历每个玩家,每次从牌堆中取出一张牌并添加到当前玩家的手牌列表中。最后返回包含三个玩家手牌信息的字典。
- def deal_cards(deck):
- """
- 发牌给三个玩家。
- :param deck: 扑克牌列表。
- :return: 包含三个玩家手牌的字典。
- """
- players = {'江煜煋': [], '周自横': [], '易相逢': []}
- for _ in range(17):
- for player in players:
- players[player].append(deck.pop())
- return players
display_cards
函数是整个斗地主发牌程序的核心流程控制函数。
['江煜煋', '周自横', '易相逢']
,在实际应用中,可以根据用户输入来动态获取玩家名字。generate_deck
函数生成牌堆,然后使用shuffle_deck
函数洗牌,并输出相应的提示信息。之后调用deal_cards
函数进行发牌,并在发牌完成后,遍历玩家和他们的手牌,对手牌进行排序并将排序后的手牌以字符串形式输出。这里使用了sorted
函数对手牌列表进行排序,排序依据是我们在PokerCard
类中定义的__lt__
比较方法。- def display_cards(players):
- """
- 斗地主发牌程序的主要流程。
- :param players: 玩家列表。
- """
- print("********** 欢迎进入XXX斗地主 **********")
- for player in players:
- print(f"请输入玩家姓名:{player}")
- print("洗牌中...")
- deck = generate_deck()
- shuffled_deck = shuffle_deck(deck)
- print("洗牌完成!")
- print("发牌中...")
- dealt_players = deal_cards(shuffled_deck)
- print("发牌完成!")
- for player, cards in dealt_players.items():
- sorted_cards = sorted(cards)
- card_str = ", ".join(str(card) for card in sorted_cards)
- print(f"{player}: {card_str}")
- landlord = input("谁叫地主? ")
- landlord_cards = dealt_players[landlord]
- landlord_extra_cards = shuffled_deck[-3:]
- print(f"地主张牌:{', '.join(str(card) for card in landlord_extra_cards)}")
- landlord_cards += landlord_extra_cards
- sorted_landlord_cards = sorted(landlord_cards)
- landlord_card_str = ", ".join(str(card) for card in sorted_landlord_cards)
- print(f"{landlord}(地主): {landlord_card_str}")
- for player, cards in dealt_players.items():
- if player == landlord:
- continue
- sorted_cards = sorted(cards)
- card_str = ", ".join(str(card) for card in sorted_cards)
- print(f"{player}: {card_str}")
- class PokerCard:
- def __init__(self, point, color):
- """
- 扑克牌类的构造函数。
- :param point: 扑克牌的点数。
- :param color: 扑克牌的花色。
- """
- self.point = point
- self.color = color
- # 自定义权重,用于比较大小
- self.weight = self.get_weight()
-
- def get_weight(self):
- """
- 计算扑克牌的权重,用于比较大小。
- :return: 扑克牌的权重值。
- """
- 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}
- colors = {'♠': 4, '♥': 3, '♦': 2, '♣': 1}
- if self.point == 'Joker':
- return 999 # 可以根据需要设置一个较大的值表示大小王的权重
- else:
- return points[self.point] * 10 + colors[self.color]
-
- def __str__(self):
- """
- 返回扑克牌的字符串表示。
- :return: 扑克牌的字符串形式。
- """
- return f'{self.point}{self.color}'
-
- def __repr__(self):
- """
- 返回扑克牌在交互环境中的表示形式,与__str__方法类似。
- :return: 扑克牌的字符串形式。
- """
- return f'{self.point}{self.color}'
-
- def __lt__(self, other):
- """
- 定义小于比较方法,用于扑克牌的排序。
- :param other: 另一个扑克牌对象。
- :return: 如果当前扑克牌权重小于另一个,则返回 True,否则返回 False。
- """
- return self.weight < other.weight
-
-
- def generate_deck():
- """
- 生成一副扑克牌。
- :return: 包含 54 张扑克牌的列表。
- """
- points = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2']
- colors = ['♠', '♥', '♦', '♣']
- deck = [PokerCard(point, color) for point in points for color in colors]
- deck += [PokerCard('Joker', '大'), PokerCard('Joker', '小')]
- return deck
-
-
- def shuffle_deck(deck):
- """
- 随机洗牌。
- :param deck: 扑克牌列表。
- :return: 洗牌后的扑克牌列表。
- """
- import random
- random.shuffle(deck)
- return deck
-
-
- def deal_cards(deck):
- """
- 发牌给三个玩家。
- :param deck: 扑克牌列表。
- :return: 包含三个玩家手牌的字典。
- """
- players = {'玩家A': [], '玩家B': [], '玩家C': []}
- for _ in range(17):
- for player in players:
- players[player].append(deck.pop())
- return players
-
-
- def display_cards(players):
- """
- 斗地主发牌程序的主要流程。
- :param players: 玩家列表。
- """
- print("********** 欢迎进入XXX斗地主 **********")
- for player in players:
- print(f"请输入玩家姓名:{player}")
- print("洗牌中...")
- deck = generate_deck()
- shuffled_deck = shuffle_deck(deck)
- print("洗牌完成!")
- print("发牌中...")
- dealt_players = deal_cards(shuffled_deck)
- print("发牌完成!")
- for player, cards in dealt_players.items():
- sorted_cards = sorted(cards)
- card_str = ", ".join(str(card) for card in sorted_cards)
- print(f"{player}: {card_str}")
- landlord = input("谁叫地主? ")
- landlord_cards = dealt_players[landlord]
- landlord_extra_cards = shuffled_deck[-3:]
- print(f"地主张牌:{', '.join(str(card) for card in landlord_extra_cards)}")
- landlord_cards += landlord_extra_cards
- sorted_landlord_cards = sorted(landlord_cards)
- landlord_card_str = ", ".join(str(card) for card in sorted_landlord_cards)
- print(f"{landlord}(地主): {landlord_card_str}")
- for player, cards in dealt_players.items():
- if player == landlord:
- continue
- sorted_cards = sorted(cards)
- card_str = ", ".join(str(card) for card in sorted_cards)
- print(f"{player}: {card_str}")
-
-
- display_cards(['玩家A', '玩家B', '玩家C'])
本文详细介绍了一个使用 Python 实现的斗地主发牌程序。通过设计PokerCard
类来表示扑克牌,实现了扑克牌的属性、权重计算、字符串表示和大小比较等功能。利用generate_deck
、shuffle_deck
和deal_cards
等函数完成了牌堆的生成、洗牌和发牌操作。display_cards
函数则整合了整个发牌流程,包括欢迎信息、玩家输入、洗牌发牌展示以及地主相关的处理。希望本文能为读者在开发纸牌游戏相关程序时提供有益的参考和启发,进一步探索和完善斗地主游戏程序以及其他类似的纸牌游戏程序的开发。