Python Blackjack游戏报错:AttributeError: 'set' object has no attribute 'append'
解决Blackjack游戏下注非5000金额时的AttributeError错误
问题场景
开发Python版二十一点游戏时,下注最大金额5000时运行正常,但输入其他金额时触发以下错误:
Traceback (most recent call last): File "c:\Users\Sufysam.DESKTOP-MTN757F\Desktop\Projects\blackjack.py", line 213, in <module> main() File "c:\Users\Sufysam.DESKTOP-MTN757F\Desktop\Projects\blackjack.py", line 55, in main move = getMove(playerHand, money - bet) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "c:\Users\Sufysam.DESKTOP-MTN757F\Desktop\Projects\blackjack.py", line 201, in getMove moves.append('(D)ouble down') ^^^^^^^^^^^^ AttributeError: 'set' object has no attribute 'append'
完整代码
import random, sys HEARTS = chr(9829) DIAMONDS = chr(9830) SPADES = chr(9824) CLUBS = chr(9827) BACKSIDE = 'backside' def main(): print('''Blackjack: Rules: Try to get as close to 21 without going over. Kings, Queens, and Jacks are worth 10 points. Aces are worth 1 or 11 points. Cards 2 through 10 are worth their face value. (H)it to take another card. (S)tand to stop taking cards. On your first play, you can (D)ouble down to increase your bet but must hit exactly one more time before standing. In case of a tie, the bet is returned to the player. The dealer stops hitting at 17.''') money = 5000 while True: if money <= 0: print('You\'re broke!') print("Good thing you weren't playing with real money") print('Thanks for playing!') sys.exit() print('Money:', money) bet = getBet(money) deck = getDeck() dealerHand = [deck.pop(), deck.pop()] playerHand = [deck.pop(), deck.pop()] print('Bet:', bet) while True: displayHands(playerHand, dealerHand, False) print() if getHandValue(playerHand) > 21: break move = getMove(playerHand, money - bet) if move == 'D': additonalbet = getBet(min(bet, (money - bet))) bet += additonalbet print('Bet increased to {}.'.format(bet)) print('Bet:', bet) if move in ('H', 'D'): newCard = deck.pop() rank, suit = newCard print('You drew a {} of {}.'.format(rank, suit)) playerHand.append(newCard) if getHandValue(playerHand) > 21: continue if move in ('S', 'D'): break if getHandValue(playerHand) <= 21: while getHandValue(dealerHand) < 17: print('Dealer hits...') dealerHand.append(deck.pop()) displayHands(playerHand, dealerHand, False) if getHandValue(dealerHand) > 21: break input('Press Enter to contiue...') print('\n\n') displayHands(playerHand, dealerHand, True) playerValue = getHandValue(playerHand) dealerValue = getHandValue(dealerHand) if dealerValue > 21: print('Dealer busts! You win ${}!'.format(bet)) money += bet elif (playerValue > 21) or (playerValue < dealerValue): print(' You lost!') money -= bet elif playerValue > dealerValue: print('You won ${}!'.format(bet)) money += bet elif playerValue == dealerValue: print('It\s a tie, the bet is returned to you') input('Press Enter to continue...') print('\n\n') def getBet(maxBet): while True: print('How much do you bet? (1-{}, or QUIT)'.format(maxBet)) bet = input('> ').upper().strip() if bet == 'QUIT': print('Thanks for playing!') sys.exit() if not bet.isdecimal(): continue bet = int(bet) if 1 <= bet <= maxBet: return bet def getDeck(): deck = [] for suit in (HEARTS, DIAMONDS, SPADES, CLUBS): for rank in range(2, 11): deck.append((str(rank), suit)) for rank in ('J', 'Q', 'K', 'A'): deck.append((rank, suit)) random.shuffle(deck) return deck def displayHands(playerHand, dealerHand, showDealerHand): print() if showDealerHand: print('Dealer: ', getHandValue(dealerHand)) else: print('Dealer : ???') displayCards([BACKSIDE] + dealerHand[1:]) print('PLAYER:', getHandValue(playerHand)) displayCards(playerHand) def getHandValue(cards): value = 0 numberofAces = 0 for card in cards: rank = card[0] if rank =='A': numberofAces += 1 elif rank in ('K', 'Q', 'J'): value += 10 else: value += int(rank) value += numberofAces for i in range(numberofAces): if value + 10 <= 21: value += 10 return value def displayCards(cards): rows = ['', '', '', '', ''] for i, card in enumerate(cards): rows[0] += ' ___ ' if card == BACKSIDE: rows[1] += '|## | ' rows[2] += '|###| ' rows[3] += '|_##| ' else: rank, suit = card rows[1] += '|{} | '.format(rank.ljust(2)) rows[2] += '| {} | '.format(suit) rows[3] += '|_{}| '.format(rank.rjust(2, '_')) for row in rows: print(row) def getMove(playerHand, money): while True: moves = {'(H)it', '(S)tand'} if len(playerHand) == 2 and money > 0: moves.append('(D)ouble down') movePrompt = ', '.join(moves) + '> ' move = input(movePrompt).upper() if move in ('H', 'S'): return move if move == 'D' and '(D)ouble Down' in moves: return move if __name__ == "__main__": main()
问题分析
- 错误核心:
getMove函数中,moves被定义为集合(set)(用{}包裹),而集合没有append方法,只有列表(list)才支持该操作。 - 下注5000时无报错的原因:此时
money - bet = 5000 - 5000 = 0,if len(playerHand) == 2 and money > 0:条件不成立,不会执行moves.append,因此不会触发错误。当下注其他金额时,money - bet > 0,条件成立,调用集合的append方法就会抛出AttributeError。 - 额外问题:原代码中判断双倍下注时,字符串大小写不一致——
moves里添加的是'(D)ouble down',但判断时写的是'(D)ouble Down',会导致该选项无法正常触发。
修复代码
修改getMove函数,将moves从集合改为列表,并修正大小写不一致问题:
def getMove(playerHand, money): while True: # 改为列表格式 moves = ['(H)it', '(S)tand'] if len(playerHand) == 2 and money > 0: moves.append('(D)ouble down') movePrompt = ', '.join(moves) + '> ' move = input(movePrompt).upper() if move in ('H', 'S'): return move # 修正字符串大小写,与添加的内容一致 if move == 'D' and '(D)ouble down' in moves: return move
内容的提问来源于stack exchange,提问作者Shayaan Khan
相关产品推荐
相关产品推荐

