用 Python 实现 21 点游戏(二):发牌初始化与回合流程搭建
上一篇我们已经完成了扑克牌(Card)与牌堆(Deck)的基础类。这一篇我们进入游戏主控类 Game 的搭建:先实现「加牌」方法,再完成「发牌初始化」,最后把玩家回合、庄家回合、结算等流程串起来,并运行验证发牌与手牌显示效果。
一、目标
本次要完成三件事:
- 为游戏增加「继续要牌」的方法
hit,可对玩家或庄家的手牌追加一张牌。 - 实现发牌初始化
deal_init:玩家与庄家各发两张牌,并显示手牌(庄家保留一张底牌不显示)。 - 定义
play主流程,依次调用发牌、显示手牌、玩家回合、庄家回合、结算等方法,先跑通整体骨架。
二、实现「继续要牌」方法 hit
hit 用于给指定的一手牌追加一张牌。由于玩家和庄家都可能要牌,所以方法需要接收一个 hand 参数,表示「给谁的手牌加牌」。
在 Game 类中新增:
def hit(self, hand):
# 从牌堆发一张牌,追加到指定手牌中
hand.add_card(self.deck.deal())
这里复用了前面已经写好的两个能力:Hand.add_card() 负责把牌加入手牌,Deck.deal() 负责从牌堆发出一张牌。之所以前面在 Deck 部分写了示例代码并演示过效果,就是为了在这里可以直接拿来用——deal() 返回的正是一个 Card 对象。
三、实现发牌初始化 deal_init
发牌规则:玩家一张、庄家一张、玩家一张、庄家一张,共四张牌。两张牌无论如何都不会超过 21 点,所以初始化阶段不需要判断爆牌。
def deal_init(self):
# 玩家和庄家各发两张牌
self.player_hand.add_card(self.deck.deal())
self.dealer_hand.add_card(self.deck.deal())
self.player_hand.add_card(self.deck.deal())
self.dealer_hand.add_card(self.deck.deal())
四、显示手牌 show_the_hand
发完牌后要展示牌面:玩家手牌全部亮出,庄家只显示一张,另一张作为底牌用问号代替。
def show_the_hand(self):
# 显示玩家手牌
print("玩家手牌:")
for card in self.player_hand.cards:
print(card)
# 显示庄家手牌,只亮一张,另一张为底牌
print("庄家手牌:")
print(self.dealer_hand.cards[0], "?")
玩家手牌通过遍历 cards 全部打印;庄家则直接取列表第一张,第二张不显示,用 ? 让玩家去猜。

五、搭建 play 主流程
把各个阶段按顺序串起来。玩家回合、庄家回合、结算先占位(pass),后续再逐步丰富。
def player_turn(self):
pass
def dealer_turn(self):
pass
def game_over(self):
pass
def show_result(self):
pass
def play(self):
self.deal_init() # 各发两张牌
self.show_the_hand() # 展示牌面信息
self.player_turn() # 玩家回合
self.dealer_turn() # 庄家回合
self.game_over() # 游戏结束
self.show_result() # 显示结果
在类内部调用其他方法,直接使用 self.方法名() 即可。整个调用链非常清晰:外部只操作 Game 类,Game 内部通过 self 调度各阶段,各阶段再调用 Card、Deck、Hand 等类相互配合。
六、测试运行
实例化并启动游戏:
game = Game()
game.play()
运行后可以看到:程序先给玩家发两张、再给庄家发两张,与真实游戏开局一致。输出中玩家手牌完整显示(如红桃 J、黑桃 9),庄家手牌只显示一张,另一张用问号代替——这正是底牌不让你看到的效果。

七、小结
本篇完成了游戏骨架的关键一步:
hit(hand):复用Hand.add_card()与Deck.deal(),实现按手牌追加一张牌;deal_init():玩家、庄家交替各发两张;show_the_hand():玩家全亮、庄家留一张底牌;play():把发牌、显示、玩家回合、庄家回合、结算按顺序串起来。
发牌与手牌显示已经跑通,玩家回合、庄家回合、结算目前还是占位方法。下一篇我们将依次实现这些方法,让游戏真正可以「要牌、停牌、比大小」。
动图规划建议:录制一次
game.play()从发牌到输出手牌的完整控制台过程,突出庄家底牌以问号隐藏的效果,适合放在「测试运行」小节末尾。
想系统学习这门课程?
你已阅读完本文。需要更完整的知识体系,可以继续了解「Vibe Coding 实战课程」。
查看课程详情