You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blackjack游戏触发RecursionError:递归深度超出问题求助

解决Blackjack游戏中的RecursionError问题

错误根源分析

看回溯信息就能发现,问题根本不在random.shuffle(),而是Dealer类的无限递归实例化:

def __init__(self, player_name):
    self._hand = []
    self._deck = Deck()
    self._player = Player(player_name)
    self._dealer = Dealer('Dealer')  # 这里是罪魁祸首!

每次创建Dealer对象时,构造函数里都会再创建一个新的Dealer实例,这个新实例又会重复执行同样的逻辑,无限循环下去,直到触发Python的递归深度限制,抛出RecursionError。报错点落在random.shuffle()只是因为递归过程中多次调用了Deck的populate方法,属于连锁反应。

修复方案

1. 重构Dealer类的设计

Dealer本质上也是一个玩家,没必要自己实例化自己,直接复用Player类即可:

class Dealer:
    def __init__(self, player_name):
        self._deck = Deck()
        self._player = Player(player_name)
        self._dealer_player = Player('Dealer')  # 用Player实例表示庄家

之后把所有原来用到self._dealer的地方,全部替换成self._dealer_player,比如发牌、计算分数的逻辑。

2. 修复Player类的变量错误

Player的get_score方法里有个笔误,把score写成了value:

# 错误代码
while aces > 0 and score > 21:
    value -= 10
    aces -= 1

# 修正后
while aces > 0 and score > 21:
    score -= 10
    aces -= 1

3. 移除冗余测试代码

代码开头的Deck测试会在游戏启动前就执行,影响正常流程,建议注释或删除:

#Test
my_deck = Deck()
print(my_deck)

修复后的完整代码

import random

class Card:
    def __init__(self, suit, number):
        self._suit = suit
        self._number = number

    def __repr__(self):
        return self._number + ' of ' + self._suit

    @property
    def suit(self):
        return self._suit
    
    @suit.setter
    def suit(self, suit):
        if suit in ['Hearts', 'Clubs', 'Diamonds', 'Spades']:
            self._suit = suit
        else: 
            print("That's not a valid suit")

    @property
    def number(self):
        return self._number
    
    @number.setter
    def number(self, number):
        if number in ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']:
            self._number = number
        else:
            print("That's not a valid number")
        

class Deck:
    def __init__(self):
        self._cards = []
        self.populate()
    
    def __repr__(self) -> str:
        return f'{self._cards}'

    def populate(self):
        suits = ['Hearts', 'Clubs', 'Diamonds', 'Spades']
        numbers = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']

        cards = []
        for suit in suits:
            for number in numbers:
                cards.append(Card(suit, number))    
        
        self._cards = cards
        random.shuffle(self._cards)

class Player:
    def __init__(self, name, hand=None, score=0):
        self._name = name
        self._hand = [] if hand is None else hand
        self._score = score
    
    def add_card(self, card):
        self._hand.append(card)
    
    def get_score(self):
        score = 0
        aces = 0
        for card in self._hand:
            if card.number == 'A':
                aces += 1
                score += 11
            elif card.number in ['J', 'Q', 'K']:
                score += 10
            else:
                score += int(card.number)
        
        while aces > 0 and score > 21:
            score -= 10
            aces -= 1
        
        return score

class Dealer:
    def __init__(self, player_name):
        self._deck = Deck()
        self._player = Player(player_name)
        self._dealer_player = Player('Dealer')
    
    def first_cards(self):
        self._player.add_card(self._deck._cards.pop())
        self._dealer_player.add_card(self._deck._cards.pop())
        self._player.add_card(self._deck._cards.pop())
        self._dealer_player.add_card(self._deck._cards.pop())

    def player_turn(self):
        while self._player.get_score() < 21:
            choice = str(input('Do you want to hit? (Y/N)')).lower()
            if choice == 'y':
                self._player.add_card(self._deck._cards.pop())
                print(f'Your current score is : {self._player.get_score()}')
            else:
                break

    def dealer_turn(self):
        while self._dealer_player.get_score() < 17:
            self._dealer_player.add_card(self._deck._cards.pop())
        print(f'The dealer\'s score is: {self._dealer_player.get_score()}')

    def start(self):
        print('Welcome to blackjack! By Nils Edstrom')
        self.first_cards()
        # 庄家初始只显示一张牌的分数,更符合真实规则
        dealer_visible_score = self._dealer_player._hand[1].number
        dealer_visible_score = 11 if dealer_visible_score == 'A' else 10 if dealer_visible_score in ['J','Q','K'] else int(dealer_visible_score)
        print(f'Your current score is: {self._player.get_score()}')
        print(f'The dealer\'s visible score is: {dealer_visible_score}')

        self.player_turn()
        if self._player.get_score() > 21:
            print(f'You lose! Your current score is: {self._player.get_score()}')
            return
        
        self.dealer_turn()
        if self._dealer_player.get_score() > 21:
            print('You won! Dealer busted.')
        elif self._player.get_score() > self._dealer_player.get_score():
            print('You won!')
        elif self._player.get_score() < self._dealer_player.get_score():
            print('The dealer won!')
        else:
            print('It\'s a tie!')

player1 = str(input('What is your name? '))
dealer = Dealer(player1)
dealer.start()

内容的提问来源于stack exchange,提问作者Nils Edström

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 04:45:07