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

discord.py Blackjack抽牌函数返回None问题及去重算法优化求助

问题根源分析

原代码存在两个核心问题:

  • 每次调用deck()都会重新生成并洗牌整副牌,完全违背真实抽牌逻辑——你应该维护一副全局的、已洗牌的牌组,而非每次抽牌都重建牌组。
  • 递归分支无返回值:当抽到重复牌时,调用Test.deck(self)但未返回该调用的结果,导致当前函数执行到return时无有效返回值,最终返回None。
优化方案:维护全局洗牌牌组

正确思路是在类初始化时生成并洗牌完整牌组,后续抽牌直接从该牌组取牌,天然避免重复,无需额外去重检查。

修改后代码示例:

import random

class BlackJackGame:
    def __init__(self):
        # 初始化时生成整副牌并完成洗牌
        card_suits = ["Club ", "Diamond ", "Spade ", "Heart "]
        card_ranks = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "K", "Q", "A"]
        self.deck = [suit + rank for suit in card_suits for rank in card_ranks]
        random.shuffle(self.deck)
    
    def draw_card(self):
        # 牌组抽完时自动重新洗牌
        if not self.deck:
            card_suits = ["Club ", "Diamond ", "Spade ", "Heart "]
            card_ranks = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "K", "Q", "A"]
            self.deck = [suit + rank for suit in card_suits for rank in card_ranks]
            random.shuffle(self.deck)
        return self.deck.pop()
原递归逻辑的修复(不推荐)

如果非要保留原思路(不建议,效率极低),需修复递归的返回逻辑:

def deck(self):
    card_type = ["Club ", "Diamond ", "Spade ", "Heart "]
    card_nums = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "K", "Q", "A"]
    cards_total = [i + j for i in card_type for j in card_nums]
    random.shuffle(cards_total)
    pop_card = cards_total.pop()

    if pop_card in self.overlap_check:
        # 必须返回递归调用的结果
        return self.deck()
    self.overlap_check.append(pop_card)
    return pop_card

此方案弊端明显:每次抽牌都要重建、洗牌整副牌,牌组快抽完时递归深度会急剧上升,容易触发Python递归深度限制。

为什么推荐全局牌组方案?
  • 完全贴合真实二十一点游戏规则:一副牌抽完后重新洗牌。
  • 彻底规避重复抽牌问题,无需额外去重逻辑。
  • 性能更优,无冗余的牌组生成和递归操作。

内容的提问来源于stack exchange,提问作者Luminous Lunetzsche

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 14:10:40