Python 扑克牌程序实战:洗牌与发牌功能的实现
前面我们已经完成了扑克牌对象的创建,现在这副牌还是按顺序排列的。实际打牌当然不能这样,我们需要先把牌打乱,再一张张发出去。这篇文章就带大家完成洗牌和发牌两个核心功能,并把整副牌的逻辑串起来测试一遍。
一、实现目标
在 Deck 类中补充两个方法:
- 洗牌(shuffle):把初始化好的有序牌堆随机打乱。
- 发牌(deal):每次调用从牌堆顶部弹出一张牌。
洗牌依赖 Python 内置的 random 模块,发牌则利用列表的 pop() 方法实现。
二、洗牌功能的实现
洗牌的核心是 random.shuffle()。它接收一个列表,直接在原列表上做随机打乱,不会返回新列表。
先在文件顶部导入 random 模块,然后在 Deck 类中定义 shuffle 方法,把 self.cards 传进去:
import random
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]
def shuffle(self):
random.shuffle(self.cards)
这里有一个容易踩的坑:random.shuffle() 执行后没有任何返回值,它改变的是传入的原始列表本身。所以调用完洗牌后,直接查看 self.cards 就能看到打乱后的结果。
为了先验证这个方法的效果,我们可以在 IDLE 中单独测试:先生成一副有序的牌,调用 random.shuffle(cards),再输出 cards 对比前后变化。

可以看到,原本按黑桃 A、黑桃 2、黑桃 3 顺序排列的牌,经过 shuffle 后顺序完全打乱、毫无规律。这就说明洗牌逻辑是有效的。
三、发牌功能的实现
洗牌完成后,牌堆 self.cards 就是一个打乱顺序的列表。发牌就是从列表顶部取牌,用 pop() 弹出即可:
def deal(self):
return self.cards.pop()
每次调用 deal(),都会从 self.cards 中弹出一张牌并返回,同时牌堆里就少了一张。连续调用多次,就相当于连续发牌。

四、整体测试
把洗牌和发牌串起来跑一遍。先实例化 Deck 得到整副牌,遍历输出确认顺序正常:
deck = Deck()
for card in deck.cards:
print(card)
因为 Card 类中定义了 __str__ 方法,输出时会自动显示花色加点数,所以遍历打印出来的就是一副可读的、有顺序的扑克牌。

接着调用 deck.shuffle() 洗牌,再次遍历输出:
deck.shuffle()
for card in deck.cards:
print(card)
运行后对比两次输出,可以看到洗牌后的顺序已经完全改变,说明 shuffle 方法在类中同样生效。

最后测试发牌。连续调用四次 deal(),把每次返回的牌分别赋值给变量再打印:
card1 = deck.deal()
card2 = deck.deal()
card3 = deck.deal()
card4 = deck.deal()
print(card1)
print(card2)
print(card3)
print(card4)
运行结果会依次输出四张牌,它们正是洗牌后牌堆最上面的四张,且每次调用只弹出一张,符合“从上往下发牌”的预期。

五、小结
到这里,一副扑克牌的完整逻辑就实现了:
- 实例化
Deck时,初始化方法自动生成一副有规律的牌; - 调用
shuffle()时,借助random.shuffle()原地打乱牌堆; - 调用
deal()时,通过pop()从牌堆顶部弹出一张牌。
三个环节各司其职,组合起来就构成了洗牌、发牌的基础流程,后续做更复杂的发牌规则(比如庄家与玩家轮流发牌)时,直接在这个基础上扩展即可。
想系统学习这门课程?
你已阅读完本文。需要更完整的知识体系,可以继续了解「Vibe Coding 实战课程」。
查看课程详情