【问题标题】:Drawing unique cards from a deck for a game of BlackJack in Python在 Python 中为二十一点游戏从一副牌中绘制独特的牌
【发布时间】:2021-06-10 09:17:41
【问题描述】:

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

2 名玩家的结果示例如下:

Player1 的第一张牌是红桃四。 Player1 的第二张牌是梅花九。 Player2 的第一张牌是红桃四。 Player2 的第二张牌是梅花九。

我一直在审查代码并对发牌卡的功能进行修改,例如通过使用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)

【问题讨论】:

    标签: python blackjack


    【解决方案1】:

    这部分代码有误:

    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

    【讨论】:

    • 出于某种原因,执行ph = Playerhand(player) 并没有像您预期的那样真正清除手牌列表。需要修复更深层次的问题,但我在答案中找到了一个简单的解决方法。你可能也想更新你的。
    【解决方案2】:

    虽然 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()
    

    双手永远不会清空,这就是为什么它们一直输出同一只手。

    【讨论】:

    • 我得到了同样的结果,似乎ph = Playerhand(player) 没有创建新的 Playerhand 对象,但 insted 只是获取了对前一个对象的引用。知道为什么会这样吗?
    • 谢谢!这很有帮助。但我仍然不明白为什么每个玩家的初始手牌都是为他之前的其他玩家抽的牌。我认为它应该自动从每个 For 循环的空列表开始。
    • 再次回到这个话题:看来这就是正在发生的事情! stackoverflow.com/questions/4841782/…
    • 我同意@HeinerFrüh 我认为这是一个合理的解释,因为你正在发生什么。
    猜你喜欢
    • 2020-06-18
    • 2018-04-02
    • 2018-05-18
    • 1970-01-01
    • 2021-10-10
    • 2023-03-16
    • 2020-04-22
    • 1970-01-01
    • 2023-03-21
    相关资源
    最近更新 更多