在 Python 中为二十一点游戏从一副牌中绘制独特的卡片

问题描述

我正在制作一款多人游戏二十一点,并且在获取代码(在 python 中)以向多个玩家分发独特的卡片时遇到了问题。下面的代码向所有玩家发了同一套牌。

以下是 2 个玩家的结果示例:

玩家 1 的第一张牌是红心四。 Player1 的第二张牌是九个俱乐部。 Player2 的第一张牌是红心四。 玩家 2 的第二张牌是梅花九。

我一直在审查代码并对交易卡的功能进行修改,例如通过使用 while 循环遍历每个玩家并将两张牌附加到他们的手上。然而,结果并没有什么不同。

有人能指出代码中的错误在哪里吗?谢谢。

代码如下:

"""This is a game of Blackjack."""
import random


"""Defining the attributes of the cards"""
suits = ('Hearts','Diamonds','Spades','Clubs')
ranks = ('Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Jack','Queen','King','Ace')

"""Class class must be able to understand the Suit and Rank of a card"""
class Card:
    def __init__(self,suit,rank):
        self.suit = suit
        self.rank = rank

    def __str__(self):
        return self.rank + " of " + self.suit

"""Deck class must be able to:
Instantiate a new deck and hold as a list of card objects;
Shuffle a deck through a method call; and
Deal cards from the deck."""

class Deck:
    def __init__(self):
        self.all_cards = []
        for suit in suits:
            for rank in ranks:
                created_card = Card(suit,rank)
                self.all_cards.append(created_card)

    def shuffle(self):
        random.shuffle(self.all_cards)

    def deal_one(self):
        return self.all_cards.pop()

    def __str__(self):
        statement = ""
        for card in self.all_cards:
            statement = statement + card.rank + " of " + card.suit + "\n"
        return statement

"""Hand class must be able to:
Store the hands of the player;
Compute the value of each hand"""

class Playerhand:
    def __init__(self,name,hands=[[],[],[]]):
        self.name = name
        self.hands = hands

        
    def num_of_hands(self):
        num_of_hands = 0
        for hand in self.hands:
            if hand != []:
                num_of_hands += 1
            else:
                pass
        return num_of_hands

    def show_first_card(self):
        print("{}'s first card is {}".format(self.name,self.hands[0][0]))
        print("{}'s second card is {}".format(self.name,self.hands[0][1]))


    def value_of_hands(self):
        value_of_hands = []
        for hand in self.hands:
            total_value = 0
            values = {'Two':2,'Three':3,'Four':4,'Five':5,'Six':6,'Seven':7,'Eight':8,'Nine':9,'Ten':10,'Jack':10,'Queen':10,'King':10,'Ace':11}
            check_for_aces = []
            for card in hand:
                if card.suit == 'Ace':
                    check_for_aces.append('Ace')
                else:
                    pass

            for card in hand:
                total_value = total_value + values[card.rank]
                
                for item in range(0,len(check_for_aces)):
                    if total_value > 21:
                        total_value = total_value - 10
                    else:
                        pass

            value_of_hands.append(total_value)

        return value_of_hands

"""Pre-game:
Asking for the number of players to CREATE A LIST OF PLAYERS ['Dealer','P1','P2',etc.] and a DICTIONARY OF WAGERS {"P1": $X,"P2": $Y,etc.}"""

def number_of_players():
    number_of_players = input("How many players are we expecting? Please enter 1 to 7: ")
    while number_of_players.isdigit() == False or int(number_of_players) not in range(1,8):
        number_of_players = input("Only accepting integer values between 1 to 7. Please enter 1 to 7: ")
    return int(number_of_players)

def check_float(potential_float):
    try:
        float(potential_float)
        return True
    except:
        return False

def playername(no_of_players):
    print("We are expecting {} player(s). We are going to start collecting information on player names and wager!".format(no_of_players))
    player_list = ['Dealer']

    for number in range(1,no_of_players+1):
        name = input("Player {},what is your name? ".format(number))
        while name in player_list:
            name = input("Player {},your chosen name has been taken. Please give us an alternative: ")
        player_list.append(name)

    return player_list

def playerwager(player_list):
    player_wager = {}
    for number in range(1,len(player_list)):
        wager = input("{},how much are you betting? Please input number: $ ".format(player_list[number]))
        while check_float(wager) is False:
            wager = input("{},please input a valid wager in number: $ ".format(player_list[number]))
        wager = float(wager)
        player_wager[player_list[number]] = wager
        player_wager["Dealer"] = 0
    return player_wager

def dealingcards(player_list):
    newdeck = Deck()
    newdeck.shuffle()
    print(newdeck)                                                      # Remove in due course.

    for player in player_list:
        for item in range(0,2):
            Playerhand(player).hands[0].append(newdeck.deal_one())
        Playerhand(player).show_first_card()

#GAME ON
x = number_of_players()
playerlist = playername(x)
playerwager(playerlist)
dealingcards(playerlist)

解决方法

这部分代码有误:

for player in player_list:
    for item in range(0,2):
        Playerhand(player).hands[0].append(newdeck.deal_one())
    Playerhand(player).show_first_card()

你必须存储玩家手牌,而不是在显示第一张牌时重新定义它:

playerhands = []
for player in player_list:
    playerhands.append(Playerhand(player,hands=[[],[],[]]))
    for item in range(0,2):
        playerhands[-1].hands[0].append(newdeck.deal_one())
    playerhands[-1].show_first_card()

编辑:这是问题的真正根源 "Least Astonishment" and the Mutable Default Argument

,

虽然 Heiner 走在正确的轨道上,但我通过调试器发现这样做:

ph = Playerhand(player)

神秘地没有清理手。数据似乎几乎是静态的。但是,一个简单的创可贴修复如下:

for player in player_list:
    ph = Playerhand(player)
    ph.hands[0] = []
    for item in range(0,2):
        card = newdeck.deal_one()
        ph.hands[0].append(card)
    ph.show_first_card()

两手牌从来没有清零,这就是为什么他们一直输出同一手牌。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...