【问题标题】:dealing cards to players and updating dictionary with player:hand向玩家发牌并使用 player:hand 更新字典
【发布时间】:2020-11-19 07:43:50
【问题描述】:

我正在尝试创建一副牌,随机洗牌,然后将 3 张牌发给 3 位玩家。我创建了一个函数 buildDeck(),它以列表的形式返回卡组中需要的 48 张卡片。然后我尝试用键值 {playername: [3 random cards from deck]} 制作字典 playerHands。然后我 def pullCards() 洗牌,检查牌组中至少有 9 张牌,然后从牌组中随机抽取 3 张牌,并使用 pop() 将它们移除。我现在想为 dict playerHand 中的每个玩家键分配 3 张随机抽取的卡片作为值。

我是编程新手,不知道这是否适合这个程序,也不知道在列表和字典中使用列表是否适合。

我不应该为这个程序使用类,我什至不知道如何使用!真的很感激一些帮助!谢谢

import random

def printMenu():
    #prints menu of options
    menu = "s: start new game\np: Pull cards for all players\no: output deck\nh: output players’ hand\ne: exchange one card\nd: declare winner\nq: quit\nSelect an option:\n"
    print(menu)
    return
printMenu()

def buildDeck():
    suits = ['Clubs', 'Golds', 'Cups', 'Swords']
    values = list(range(1, 13))
    deck = []
    #iterates through elements in suits and elements in values appending each respective element as a new element into deck
    for i in suits:
        for x in values:
            deck.append(list([i, x]))
    return deck


def startNewGame():
    #prompts user for player names
    player1 = input("Enter player 1's name:\n")
    player2 = input("Enter player 2's name:\n")
    player3 = input("Enter player 3's name:\n")
    
    #calls 48 card deck using buildDeck() function 
    buildDeck()
    
    #creates dictionary of each player's empty hand with values of None
    playerHand = {player: None for player in [player1, player2, player3]}
    return playerHand

    
def pullCards():
    playerHand = startNewGame()
    deck = buildDeck()
    #randomly shuffles deck
    random.shuffle(deck)
    #iterates through cards in the deck and checks if at least 9 cards
    for cards in deck:
        if deck.count(cards) >= 9:
            #draws 3 random cards and pop() removes cards from the deck
            for i in range(3):
                randomCard = deck.pop(random.randint(0, len(deck) - 1))
                for keys in playerHand.keys():
                    playerHand[keys] = randomCard

【问题讨论】:

标签: python list dictionary random


【解决方案1】:

在回答你的问题的同时,请允许我给你一些提示。

  1. 如果您只需要执行一次,请不要将 printMenu 设为函数。即使需要多次使用,也可以在函数外定义菜单,除非每次调用函数时都需要重新定义。

  2. 在 buildDeck 中,可以在函数之外编写套装和套牌,就像使用菜单一样。 deck.append(list([i, x])) 可以写成 deck.append([i, x]) 因为 [i,x] 已经是一个列表了。

  3. 在 StartNewGame 中,调用 BuildDeck 没有任何作用,因为它制作的牌组没有分配给任何东西,而且您稍后会再次使用 BuildDeck。 Sean C 的建议也是正确的 - 使用 [] 而不是 None,稍后再简单地追加。

  4. 在 PullCards 中,不需要使用 random.shuffle,因为您稍后会使用 randint,除非您必须在某个时候打印牌组。即使这样,您也可以稍后删除 randint - 保留两者之一。 现在是 PullCards 中的循环。

for cards in deck:
        if deck.count(cards) >= 9:
            #draws 3 random cards and pop() removes cards from the deck
            for i in range(3):
                randomCard = deck.pop(random.randint(0, len(deck) - 1))
                for keys in playerHand.keys():
                    playerHand[keys] = randomCard

是您的原始代码。 这里的一个问题是,由于for cards in deck:,这段代码将运行48次。我不认为您打算这样做,您可以安全地删除 for 循环和一个缩进级别。 另一个是此代码随机选择一张牌,并给所有 3 名玩家相同的一张。最后是因为playerHand[keys] = randomCard,第三个randomCard是分配给字典中每个玩家键的值。你想要的是一个列表作为每个玩家键的值,每个列表有 3 张牌。

要解决这两个问题,首先我们将randomCard = deck.pop(random.randint(0, len(deck) - 1)) 移动到第二个for 循环中。 从此:

for i in range(3):
    randomCard = deck.pop(random.randint(0, len(deck) - 1))
    for keys in playerHand.keys():
        playerHand[keys] = randomCard

到这里:

for i in range(3):
    for keys in playerHand.keys():
        randomCard = deck.pop(random.randint(0, len(deck) - 1))
        playerHand[keys] = randomCard

然后将 playerHand[keys] = randomCard 更改为 playerHand[keys].append(randomCard),就像 Sean C 建议的那样,这样每个玩家键的值(我们之前更改为空列表)都会附加 3 张牌(即那些牌,那些 [i,x ] 列表,现在是此列表的元素)。

希望这会有所帮助。

【讨论】:

  • 为此,也许您应该在 pullCards 之外定义卡片组,并在 pullCards 中写入 global deck。看,在 Python(和其他语言)中有一种叫做“范围”的东西,这意味着函数中定义的变量不能在函数之外使用,并且程序中定义的变量默认情况下不能被函数更改。但是,如果你写了global deck,这会让python 识别出全局变量deck 将在这个函数被调用时被使用和改变。另外,现在您可以在函数之外使用甲板。
【解决方案2】:

我现在想为 dict playerHand 中的每个玩家键分配 3 张随机抽取的牌作为值

我在 startNewGame 中将 playerHand = {player: None 更改为 playerHand = {player: [] 以便您可以将卡片附加到 pullCards 中的列表中,然后对后者的逻辑进行排序,这样您最终每个玩家手中都有 3 张卡片。我不确定甲板长度的测试是否适合您 - 如果不是,请移动它(len(deck) 如果没问题 - 无法通过迭代看到您想要做什么)。它在这里运行良好 - 希望对您有所帮助。

def startNewGame():
    #prompts user for player names
    player1 = input("Enter player 1's name:\n")
    player2 = input("Enter player 2's name:\n")
    player3 = input("Enter player 3's name:\n")
    
    #calls 48 card deck using buildDeck() function 
    buildDeck()
    
    #creates dictionary of each player's empty hand with values of None
    playerHand = {player: [] for player in [player1, player2, player3]}
    return playerHand

    
def pullCards():
    playerHand = startNewGame()
    deck = buildDeck()
    #randomly shuffles deck
    random.shuffle(deck)
    #checks if at least 9 cards
    #draws 3 random cards and pop() removes cards from the deck
    for player in playerHand: # 'for' iterates through the dict's keys
        for i in range(3):
            if len(deck) >= 9:
                randomCard = deck.pop(random.randint(0, len(deck) - 1))
                playerHand[player].append(randomCard)
    
    print(playerHand)

pullCards()

给予

{'w': [['Clubs', 6], ['Golds', 10], ['Cups', 6]], 'e': [['Clubs', 7], ['Golds', 7], ['Golds', 1]], 'r': [['Golds', 12], ['Clubs', 12], ['Cups', 4]]}

另外,刚刚看到buildDeck() 运行了两次,但在 startNewGame 中什么也不做 - 从那里删除它或将其分配给一个 var 并将其传递给 pullCards

【讨论】:

  • @angus-watters 只需在 buildDeck() 的顶部声明 global deck,deck 将位于所有内容的全局命名空间中 - 除非您尝试在函数中重新分配它,因为它会静默成为该 func 的本地 var 并且对同名的全局 var 没有影响
  • @ang-wg2 了解 string.join() - 这应该会让你正确,大约在页面的一半处 realpython.com/python-string-split-concatenate-join 。请注意,一旦您加入了手牌列表中的所有“卡片”列表,您将获得一个字符串列表,您可以再次 .joun 以创建一个大的非列表字符串。如果您使用 '\n' 加入,则每张卡片都会换行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2017-05-16
  • 2014-12-18
  • 1970-01-01
  • 2021-02-07
  • 1970-01-01
相关资源
最近更新 更多