Python 21点游戏实战:从单张牌到一副扑克牌的生成
在前面我们已经完成了单张扑克牌的表示,这一节我们要把单张牌扩展成一副完整的扑克牌。21点游戏和普通扑克牌玩法一样,需要一副去掉大小王、共 52 张的牌,并且能够随机抽牌、洗牌。本文就带你用面向对象的方式,一步步生成这副牌。
一、目标
我们要在牌堆类中新增一个初始化方法,让它自动生成一副完整的扑克牌,包含:
- 4 种花色:黑桃、红心、梅花、方块
- 13 个牌值:A、2~10、J、Q、K
- 组合后共 52 张牌,每张牌都是一个
Card对象
二、准备花色与牌值
先在初始化方法中定义花色列表 suits,共四个值:
suits = ['黑桃', '红心', '梅花', '方块']
接着定义牌值列表 ranks。数字部分用 range 生成 2 到 10,并转成字符串,再拼上 A、J、Q、K:
ranks = [str(i) for i in range(2, 11)]
ranks = ['A'] + ranks + ['J', 'Q', 'K']
这样 ranks 的顺序就是 A、2、3……10、J、Q、K,符合我们平时看牌的习惯。
写完后可以先验证一下 ranks 是否符合预期。写小片段代码时,用 IDLE 交互环境非常方便,不会影响前面已经写好的代码。运行后输出结果为:
['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']

三、用列表生成式组合出一副牌
花色和牌值都准备好了,接下来用列表生成式把两者两两组合。这里使用两个 for 循环,外层遍历花色,内层遍历牌值:
cards = [(suit, rank) for suit in suits for rank in ranks]
把这段代码贴到 IDLE 中运行,可以看到输出就是一副完整的扑克牌:从黑桃 A 开始,依次到黑桃 K,接着是红桃 A 到红桃 K,再到梅花、方块,一共 52 张,正好去掉了大小王。

四、把元组升级为 Card 对象
上面生成的是一个列表,列表里每个元素是 (花色, 牌值) 这样的元组。但在面向对象的写法里,我们前面已经定义了 Card 类,所以更希望列表里装的是一个个 Card 对象,而不是元组。
关键代码如下:

完整代码如下:
class Card:
def __init__(self, suit, rank):
self.suit = suit
self.rank = rank
def __str__(self):
return self.suit + self.rank
class Deck:
def __init__(self):
suits = ['♠', '♥', '♣', '♦']
ranks = ['A'] + [str(i) for i in range(2, 11)] + ['J', 'Q', 'K']
self.cards = [Card(suit, rank) for suit in suits for rank in ranks]
class Hand:
"""一手牌(庄家和玩家共用)"""
pass
class Game:
"""控制整体游戏流程"""
pass
这正是面向对象比较核心的思路:让集合中的每一项都是对象,后续抽牌、比大小等操作都可以直接调用对象的方法和属性,和最开始单张牌的演示保持一致。
五、小结
本节完成了从单张牌到一副牌的构建,关键点有三个:
- 用
suits和ranks两个列表分别描述花色与牌值; - 用双重
for的列表生成式做笛卡尔积,得到 52 张牌; - 把生成的元组替换为
Card对象,为后续洗牌、抽牌打好面向对象的基础。
下一节我们就可以在这副牌的基础上实现洗牌和随机抽牌了。
想系统学习这门课程?
你已阅读完本文。需要更完整的知识体系,可以继续了解「Vibe Coding 实战课程」。
查看课程详情