用Python写炸金花游戏
文章目录
- **代码分解与讲解**
- 1. **扑克牌的生成与洗牌**
- 2. **给玩家发牌**
- 3. **打印玩家的手牌**
- 4. **定义牌的优先级**
- 5. **判断牌型**
- 6. **确定牌型优先级**
- 7. **比较两手牌的大小**
- 8. **计算每个玩家的牌型并找出赢家**
- 9. **打印结果**
- 完整代码
以下游戏规则:
那么我们要实现的功能,就是以下几个:
- 生成扑克牌。
- 随机洗牌并分发给五名玩家,每人三张牌。
- 判断每位玩家的牌型(例如:豹子、同花顺等)。
- 比较五名玩家的牌型,得出赢家。
代码分解与讲解
1. 扑克牌的生成与洗牌
suit_cards = ['黑桃', '红桃', '方块', '梅花'] # 花色
check_number = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'] # 点数
# 嵌套循环生成扑克牌
# poker_list = [f"{suit}{check}" for suit in suit_cards for check in check_number]
poker_list = []
for suit in suit_cards:
for check in check_number:
poker_list.append(f"{suit}{check}")
random.shuffle(poker_list) # 洗牌
功能:
- 通过嵌套循环,生成一副完整的扑克牌(共 52 张)。
- 例如,“黑桃2”、“红桃A” 等。
- 使用
random.shuffle()
对扑克牌列表进行随机洗牌,确保发牌的随机性。 - 这里面把存储牌的容器设置为列表
poker_list
,其实集合set
也可以,不过集合有随机性,还是喜欢都在掌握中的感觉,而且列表方便管理。
2. 给玩家发牌
player = ['player1', 'player2', 'player3', 'player4', 'player5'] # 玩家列表
# player_poker = {p: [] for p in player} # 初始化每个玩家的手牌为空列表(字典推导式)
player_poker = {} # 初始化一个空字典
for p in player: # 遍历每个玩家
player_poker[p] = [] # 为每个玩家赋值一个空列表,表示其手牌,player_poker是个字典,键是用户,列表是值(也就是玩家手牌)
# 确保牌的数量足够分发
if len(poker_list) < len(player) * 3:
raise ValueError("牌堆中牌的数量不足以分发给所有玩家!")
# 每人发三张牌
for i in range(3): # 每人发3轮
for p in player: # 嵌套循环,player中有5个,一共循环15次
poker = poker_list.pop() # 从牌堆顶部发一张牌
player_poker[p].append(poker)
功能:
- 初始化 5 名玩家,每名玩家分配一个空手牌列表。
- 检查如果牌堆中牌的数量不足,则抛出错误。
- 每名玩家每轮发一张牌,共发 3 轮,每人得到 3 张牌。
- 发牌后,每名玩家的牌存储在
player_poker
中,结构如下:{ 'player1': ['黑桃K', '方块Q', '红桃A'], 'player2': ['梅花7', '黑桃8', '红桃10'], ... }
3. 打印玩家的手牌
for player, pokers in player_poker.items(): # items是字典的方法,返回一个可迭代对象,每个元素是一个键值对
print(f"{player}的牌是:{', '.join(pokers)}")
功能:
- 将每名玩家的手牌以字符串形式打印出来,方便观察。
- .join() 是一个字符串方法,用于将列表中的元素用指定的字符串连接起来。
- ', '.join(pokers) 会将列表中的元素用逗号加空格(, )连接成一个字符串:
', '.join(['黑桃A', '红桃K', '方块Q']) # 结果: '黑桃A, 红桃K, 方块Q'
输出示例:
player1的牌是:黑桃K, 方块Q, 红桃A
player2的牌是:梅花7, 黑桃8, 红桃10
...
4. 定义牌的优先级
point_rank = {point: i for i, point in enumerate(check_number, start=2)} # 字典推导式(i,point)对
这里解释一下:point是键,i是值, 可以去看一下字典推导式的结构组成
功能:
point_rank
:定义点数的大小,数值越大点数越高。例如,“A” 的优先级最大,值为 14。{'2': 2, '3': 3, ..., 'K': 13, 'A': 14}
5. 判断牌型
def poker_type(cards): #这个cards是列表,也就是前面键值对中的值
points = sorted([card[2:] for card in cards], key=lambda x: point_rank[x]) # 提取点数并按大小排序
suits = [card[:2] for card in cards] # 提取花色(列表推导式),索引前两个字符
# 判断是否为豹子
if points[0] == points[1] == points[2]:
return '豹子', points
# 判断是否为同花顺
is_straight = (point_rank[points[2]] - point_rank[points[1]] == 1 and \
point_rank[points[1]] - point_rank[points[0]] == 1) or points == ['2', '3', 'A']
if len(set(suits)) == 1 and is_straight: # len(set(suit))==1判断一个列表或字符串中的所有元素是否相同
return '同花顺', points
# 判断是否为顺子
if is_straight:
return '顺子', points
# 判断是否为同花
if len(set(suits)) == 1:
return '同花', points
# 判断是否为对子
if points[0] == points[1] or points[1] == points[2] or points[0] == points[2]:
return '对子', points
# 如果都不是,返回单张
return '单张', points
功能:
根据玩家的三张牌,判断牌型并返回 牌型名称 和 点数列表。
- 豹子:三张点数相同。
- 同花顺:花色相同,点数连续。
- 顺子:点数连续(但花色不一定相同)。
- 同花:花色相同(但点数不一定连续)。
- 对子:两张牌点数相同。
- 单张:既不连续,也不同花或对子。
6. 确定牌型优先级
hand_rankings = ['单张', '对子', '顺子', '同花', '同花顺', '豹子']
功能:
- 定义牌型的优先级,牌型从低到高依次为:
- 单张 < 对子 < 顺子 < 同花 < 同花顺 < 豹子。
7. 比较两手牌的大小
def compare_hands(player1, player2):
type1, points1 = player1
type2, points2 = player2
# 比较牌型优先级
if hand_rankings.index(type1) > hand_rankings.index(type2):
return 1
elif hand_rankings.index(type1) < hand_rankings.index(type2):
return -1
# 如果牌型相同,逐个比较点数
for p1, p2 in zip(reversed(points1), reversed(points2)):
if point_rank[p1] > point_rank[p2]:
return 1
elif point_rank[p1] < point_rank[p2]:
return -1
# 如果点数相同
return 0
功能:
- 先比较两手牌的牌型优先级,优先级高者胜。
- 如果牌型相同,逐一比较点数,由高到低比较。
8. 计算每个玩家的牌型并找出赢家
player_hands = {player: poker_type(cards) for player, cards in player_poker.items()}
winner = max(player_hands.items(), key=lambda item: (hand_rankings.index(item[1][0]), item[1][1]))
功能:
- 遍历每名玩家的手牌,计算牌型。
- 使用
max
函数,根据牌型优先级和点数大小,找出赢家。
9. 打印结果
print("\n牌局结果:")
for player, (hand_type, points) in player_hands.items():
print(f"{player} 的牌型: {hand_type} ({', '.join(points)})")
print(f"赢家是: {winner[0]},牌型: {winner[1][0]} ({', '.join(winner[1][1])})")
功能:
- 输出每名玩家的牌型和点数。
- 输出赢家及其牌型。
输出示例:
player1 的牌型: 顺子 (10, J, Q)
player2 的牌型: 对子 (8, 8, K)
player3 的牌型: 单张 (7, 9, A)
player4 的牌型: 同花 (4, 6, J)
player5 的牌型: 豹子 (K, K, K)
赢家是: player5,牌型: 豹子 (K, K, K)
完整代码
import random
# 定义扑克牌花色和点数
suit_cards = ['黑桃', '红桃', '方块', '梅花']
check_number = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
# 生成扑克牌
poker_list = [f"{suit}{check}" for suit in suit_cards for check in check_number]
random.shuffle(poker_list) # 洗牌
# 玩家和玩家手牌
player = ['player1', 'player2', 'player3', 'player4', 'player5']
player_poker = {p: [] for p in player}
# 发牌,每人发三张
if len(poker_list) < len(player) * 3:
raise ValueError("牌堆中牌的数量不足以分发给所有玩家!")
for i in range(3):
for p in player:
poker = poker_list.pop()
player_poker[p].append(poker)
# 打印每个玩家的牌
for player, pokers in player_poker.items():
print(f"{player}的牌是:{', '.join(pokers)}")
# 定义点数优先级
point_rank = {point: i for i, point in enumerate(check_number, start=2)}
# 判断牌型
def poker_type(cards):
points = sorted([card[2:] for card in cards], key=lambda x: point_rank[x])
suits = [card[:2] for card in cards]
# 判断是否为豹子
if points[0] == points[1] == points[2]:
return '豹子', points
# 判断是否为同花顺
is_straight = (point_rank[points[2]] - point_rank[points[1]] == 1 and \
point_rank[points[1]] - point_rank[points[0]] == 1) or points == ['2', '3', 'A']
if len(set(suits)) == 1 and is_straight:
return '同花顺', points
# 判断是否为顺子
if is_straight:
return '顺子', points
# 判断是否为同花
if len(set(suits)) == 1:
return '同花', points
# 判断是否为对子
if points[0] == points[1] or points[1] == points[2] or points[0] == points[2]:
return '对子', points
# 否则为单张
return '单张', points
# 定义牌型优先级
hand_rankings = ['单张', '对子', '顺子', '同花', '同花顺', '豹子']
# 比较两手牌的大小
def compare_hands(player1, player2):
type1, points1 = player1
type2, points2 = player2
# 比较牌型优先级
if hand_rankings.index(type1) > hand_rankings.index(type2):
return 1
elif hand_rankings.index(type1) < hand_rankings.index(type2):
return -1
# 如果牌型相同,逐个比较点数
for p1, p2 in zip(reversed(points1), reversed(points2)):
if point_rank[p1] > point_rank[p2]:
return 1
elif point_rank[p1] < point_rank[p2]:
return -1
# 如果点数相同,结果为平局
return 0
# 计算每个玩家的牌型
player_hands = {player: poker_type(cards) for player, cards in player_poker.items()}
# 找出最大牌
winner = max(player_hands.items(), key=lambda item: (hand_rankings.index(item[1][0]),
[point_rank[point] for point in item[1][1]]))
# 打印结果
print("\n牌局结果:")
for player, (hand_type, points) in player_hands.items():
print(f"{player} 的牌型: {hand_type} ({', '.join(points)})")
print(f"赢家是: {winner[0]},牌型: {winner[1][0]} ({', '.join(winner[1][1])})")