Python Blackjack项目遇IndexError: list index out of range错误求助
Python二十一点游戏IndexError问题修复
问题概述
开发二十一点游戏时触发IndexError: list index out of range,报错指向player1cards[0]或player1cards[1],提示这两个列表为空。调用draw_cards函数试图修改全局列表但未生效,尝试过多种调试方法仍未解决。
核心错误原因
- 局部变量覆盖全局变量:
rungame函数内部声明player1cards = []和dealercards = [],创建局部变量覆盖全局同名列表。draw_cards修改的是全局列表,但rungame后续访问的是局部空列表,导致索引越界。 - 重复初始化与无效调用:
rungame开头调用draw_cards后,随即被局部变量初始化清空;下注后再次初始化列表并调用draw_cards,此时列表仍是局部变量,若抽卡逻辑异常会导致列表为空。 - 抽卡时的错误删除:
hit和庄家抽卡环节执行del cardlist[card],但card是全局旧变量,并非当前抽到的dealcard,错误删除卡片导致cardlist提前耗尽,后续抽卡失败。 - 已抽卡片列表重复初始化:全局范围内重复赋值
dealt_cards=[],导致抽卡去重逻辑失效,可能出现无限循环或抽卡失败。
修复步骤
- 移除局部变量声明:删除
rungame函数内的player1cards = []和dealercards = [],确保使用全局列表。 - 修复卡片删除逻辑:将
del cardlist[card]替换为用dealt_cards记录已抽卡片,避免直接修改cardlist。 - 清理重复初始化:删除全局范围内的第二次
dealt_cards=[]赋值,保留初始的dealt_cards = []。 - 移除无效抽卡调用:删除
rungame开头的draw_cards()调用,只保留下注后的一次抽卡,并在每次游戏前重置dealt_cards。
优化建议
- 避免全局变量:改用函数参数、返回值或类封装游戏状态(如玩家手牌、庄家手牌、筹码),减少全局变量带来的意外覆盖问题。
- 优化牌组管理:生成完整牌组列表并洗牌,用
pop()方法抽卡,替代从字典中随机选择的逻辑,更符合实际发牌流程。 - 封装抽卡逻辑:将抽卡过程封装成独立函数,在
draw_cards、hit、庄家抽卡时复用,减少代码重复。 - 使用enumerate遍历:打印手牌时用
for card in dealercards:替代索引遍历,代码更简洁易读。
修复后的完整代码
import random import time def cash_out(): global playerchips total_value = playerchips[0] * 10 + playerchips[1] * 5 + playerchips[2] * 1 print(f"\nYou are cashing out. You have a total of ${total_value}.") exit() print("Welcome to the solo-blackjack casino.py. You will start with $45 dollars in chips.") player1cards = [] dealercards = [] dealt_cards = [] cardlist = { '2 of Spades': 2, '2 of Hearts': 2, '2 of Clubs': 2, '2 of Diamonds': 2, '3 of Spades': 3, '3 of Hearts': 3, '3 of Clubs': 3, '3 of Diamonds': 3, '4 of Spades': 4, '4 of Hearts': 4, '4 of Clubs': 4, '4 of Diamonds': 4, '5 of Spades': 5, '5 of Hearts': 5, '5 of Clubs': 5, '5 of Diamonds': 5, '6 of Spades': 6, '6 of Hearts': 6, '6 of Clubs': 6, '6 of Diamonds': 6, '7 of Spades': 7, '7 of Hearts': 7, '7 of Clubs': 7, '7 of Diamonds': 7, '8 of Spades': 8, '8 of Hearts': 8, '8 of Clubs': 8, '8 of Diamonds': 8, '9 of Spades': 9, '9 of Hearts': 9, '9 of Clubs': 9, '9 of Diamonds': 9, '10 of Spades': 10, '10 of Hearts': 10, '10 of Clubs': 10, '10 of Diamonds': 10, 'Jack of Spades': 10, 'Jack of Hearts': 10, 'Jack of Clubs': 10, 'Jack of Diamonds': 10, 'Queen of Spades': 10, 'Queen of Hearts': 10, 'Queen of Clubs': 10, 'Queen of Diamonds': 10, 'King of Spades': 10, 'King of Hearts': 10, 'King of Clubs': 10, 'King of Diamonds': 10, 'Ace of Spades': 11, 'Ace of Hearts': 11, 'Ace of Clubs': 11, 'Ace of Diamonds': 11 } def draw_cards(): global player1cards, dealercards, dealt_cards # 清空之前的手牌 player1cards.clear() dealercards.clear() for _ in range(2): # 给玩家和庄家各发两张牌 # 玩家抽牌 card = random.choice(list(cardlist.keys())) while card in dealt_cards: card = random.choice(list(cardlist.keys())) player1cards.append(card) dealt_cards.append(card) # 庄家抽牌 card = random.choice(list(cardlist.keys())) while card in dealt_cards: card = random.choice(list(cardlist.keys())) dealercards.append(card) dealt_cards.append(card) def calculate_hand_value(cards): value = 0 aces = 0 for card in cards: card_value = cardlist[card] if card_value == 11: aces += 1 value += card_value while value > 21 and aces: value -= 10 aces -= 1 return value def is_soft_17(cards): # 判断庄家是否拿到软17 value = calculate_hand_value(cards) if value == 17: for card in cards: if cardlist[card] == 11: return True return False # 玩家初始筹码:1个绿色($10)、5个红色($5)、10个白色($1),总计$45 playerchips = [1, 5, 10] print("Red chips are worth $5, White chips $1, and green chips $10") def rungame(): global playerchips, player1cards, dealercards, dealt_cards # 重置已抽卡片列表 dealt_cards.clear() print(f"You have {playerchips[2]} white chips, {playerchips[1]} red chips, and {playerchips[0]} green chips.") while True: Chipsbet = input("Type how many chips you would like to put in in the format of green, red, white. Example: 1, 2, 4 would be 1 green, 2 red, and 4 white: ") Chipsbet = Chipsbet.split(", ") if len(Chipsbet) != 3: print("Invalid input. Please enter the number of chips for each color.") continue try: bet_green, bet_red, bet_white = map(int, Chipsbet) except ValueError: print("Invalid input. Please enter numeric values.") continue if bet_green < 0 or bet_red < 0 or bet_white < 0: print("Invalid input. Chips cannot be negative.") continue total_bet = bet_green * 10 + bet_red * 5 + bet_white * 1 if total_bet == 0: print("You need to bet at least one chip.") continue if bet_green > playerchips[0] or bet_red > playerchips[1] or bet_white > playerchips[2]: print("You don't have enough chips to make that bet.") continue break # 扣除下注筹码 playerchips[0] -= bet_green playerchips[1] -= bet_red playerchips[2] -= bet_white total_bet = bet_green * 10 + bet_red * 5 + bet_white * 1 # 发牌 draw_cards() print(f''' You have been dealt the cards '{player1cards[0]}' and '{player1cards[1]}'. The dealer has been dealt '{dealercards[0]}' and an unknown card.''') while True: hitorout = input("Would you like to 'hit' or 'stand'? ").lower() if hitorout == 'hit': dealcard = random.choice(list(cardlist.keys())) while dealcard in dealt_cards: dealcard = random.choice(list(cardlist.keys())) player1cards.append(dealcard) dealt_cards.append(dealcard) print(f"You have been dealt '{dealcard}'.") player_value = calculate_hand_value(player1cards) print(f"Your current hand value is {player_value}.") if player_value > 21: print("Bust! You exceeded 21.") break elif hitorout == 'stand': print("You chose to stand.") break else: print("Invalid input. Please type 'hit' or 'stand'.") player_value = calculate_hand_value(player1cards) dealer_value = calculate_hand_value(dealercards) while dealer_value < 17 or (dealer_value == 17 and is_soft_17(dealercards)): dealcard = random.choice(list(cardlist.keys())) while dealcard in dealt_cards: dealcard = random.choice(list(cardlist.keys())) dealercards.append(dealcard) dealt_cards.append(dealcard) dealer_value = calculate_hand_value(dealercards) print(f"The dealer currently has the cards:") for card in dealercards: time.sleep(1) print(card) time.sleep(1) print("The dealer has either hit a soft 17 or has a card value under 17. They must draw another card.") time.sleep(1) print(f"The dealer has drawn '{dealcard}'. Current dealer value: {dealer_value}") print("The dealer's final hand is: ") for card in dealercards: time.sleep(1) print(card) time.sleep(1.5) if player_value > 21: print("You busted. You lose your bet.") elif dealer_value > 21: print("The dealer busted. You win!") playerchips[0] += bet_green * 2 playerchips[1] += bet_red * 2 playerchips[2] += bet_white * 2 elif player_value > dealer_value: print("You won! You get double the chips you put in.") playerchips[0] += bet_green * 2 playerchips[1] += bet_red * 2 playerchips[2] += bet_white * 2 elif player_value < dealer_value: print("You lost. You lose the chips you put in.") else: print("It's a tie. Dealer wins, you lose the chips you put in.") print(f"Your current chip count is: {playerchips[0]} green chips, {playerchips[1]} red chips, and {playerchips[2]} white chips.") rungame() while True: runanother=input("Do you want to 'play again', or 'cash out'? ").lower() if runanother=='cash out': cash_out() elif runanother == 'play again': rungame() else: print("Invalid response.")
内容的提问来源于stack exchange,提问作者Aiden Kelley
相关产品推荐
相关产品推荐

