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

Python开发Blackjack游戏时card_addition求和函数计算异常

问题原因

你的点数计算错误来自3个核心问题:

  • card_addition函数设计缺陷:每次调用时传入历史累计的total值,函数内部又会遍历整副手牌重新累加所有牌,导致旧牌被重复计算,点数随叫牌次数递增虚高。你给出的测试案例中,手牌['ace',2,10,8]算出24点,就是第二次叫牌时传入上次的total=13,重复累加了ace、2、10三张牌的点数导致的。
  • A牌计算逻辑冗余:先根据当前总和判断A记1还是11,再二次遍历调整的写法,在重复累加的基础上会进一步放大计算误差。
  • 代码存在多处语法、缩进错误:包括stand分支误判函数对象而非输入变量、爆点判断缩进错位、初始手牌未计算点数、语句未正确换行等问题,会导致逻辑分支不触发、运行报错。
修正方案

1. 重写无状态点数计算函数

去掉传入历史total的参数设计,每次直接根据当前手牌从头计算总和,从根源避免重复累加问题,同时简化A牌的判断逻辑:

def card_addition(hand):
    total = 0
    ace_count = 0
    # 非A牌直接加点数,A先按11计算,同时统计A的数量
    for card in hand:
        if card == "ace":
            ace_count += 1
            total += 11
        else:
            total += card
    # 只要爆点还有A可以调整,就把A从11改成1(每次减10)
    while total > 21 and ace_count > 0:
        total -= 10
        ace_count -= 1
    return total

2. 修复其他语法、逻辑错误

  • 初始发完2张手牌后立刻计算初始点数,不要等第一次叫牌才算
  • 修正stand分支判断条件,把elif hit == "s"改为elif hit_stand == "s"
  • 调整爆点判断的缩进位置,每次更新玩家点数后立刻判断是否爆点
  • 所有调用card_addition的位置只传入手牌参数,不再传入历史累计值
  • 补全庄家回合的点数计算逻辑,修正错位的打印、赋值语句

修正后可运行完整代码

import random

cards = ["ace", 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
user_hand = []
dealer_hand = []
hit_stand = "h"
bust = False

def hit(hand):
    hand.append(random.choice(cards))

# 初始发牌
for _ in range(2):
    user_hand.append(random.choice(cards))
dealer_hand.append(random.choice(cards))
dealer_hand.append("hidden")

# 计算初始手牌点数
user_total = card_addition(user_hand)
print(f"Your hand is {user_hand}, current total: {user_total}")
print(f"Dealer's hand is {dealer_hand}")

# 玩家回合
while user_total < 21 and hit_stand == "h":
    hit_stand = input("Hit or stand ? (h/s)")
    if hit_stand == "h":
        hit(user_hand)
        user_total = card_addition(user_hand)
        print(f"Your hand is {user_hand} and your total is {user_total}.")
    elif hit_stand == "s":
        print("STAND !")
    # 爆点判断
    if user_total > 21:
        bust = True
        break

# 庄家回合,玩家未爆点才触发
if not bust:
    dealer_hand.remove("hidden")
    dealer_total = card_addition(dealer_hand)
    while dealer_total < 16:
        hit(dealer_hand)
        dealer_total = card_addition(dealer_hand)
    print(f"Dealer hand is {dealer_hand} and the total is {dealer_total}.")

    # 胜负判断
    if user_total > dealer_total:
        print("You win !")
    elif dealer_total > user_total:
        print("Dealer wins !")
    else:
        print("Draw !")
else:
    print("BUST !")
逻辑验证

你之前的测试手牌['ace', 2, 10, 8]用修正后的函数计算:

  • 先将A按11计算,总和为11+2+10+8=31,共1张A
  • 31>21触发调整,把A改为1,总和减10得21,结果正确,不会再出现24的计算错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 14:24:18