【问题标题】:Why Does this Error Occur in my Python Twenty One Card Game?为什么我的 Python 21 纸牌游戏会出现此错误?
【发布时间】:2016-02-13 15:11:50
【问题描述】:

这是错误:

Traceback(最近一次调用最后一次): 文件“C:/Users/Wattel/Desktop/21 21 21.py”,第 177 行,在 主要的() 文件“C:/Users/Wattel/Desktop/21 21 21.py”,第 167 行,主要 PPOINTS, DPOINTS, PHAND, DHAND = dLoop(PHAND, DHAND, DECK) TypeError: 'NoneType' 对象不可迭代

我知道它与这段代码有关,但无法弄清楚问题到底是什么:

scoreHAND(DHAND) < 18 or scoreHAND(DHAND) < 21 and scoreHAND(DHAND) < scoreHAND(PHAND) or scoreHAND(DHAND) < 21

这是我的其余代码:

##21 Card Game 
##Wattel
##2016 Spring

from random import *
import random
from random import shuffle, randint

CARDPOINTS = {'AD': 11,'AH': 11,'AC': 11,'AS': 11,
              'KD': 10,'KH': 10,'KC': 10,'KS':10,
              'QD': 10,'QH': 10,'QC': 10,'QS': 10, 
              'JD': 10,'JH': 10,'JC': 10,'JS': 10,
              '10D': 10,'10H': 10,'10C': 10,'10S': 10,
              '9D': 9,'9H': 9,'9C': 9,'9S': 9,
              '8D': 8,'8H': 8,'8C': 8,'8S': 8,
              '7D': 7,'7H': 7,'7C': 7,'7S': 7,
              '6D': 6,'6H': 6,'6C': 6,'6S': 6,
              '5D': 5,'5H': 5,'5C': 5,'5S': 5,
              '4D': 4,'4H': 4,'4C': 4,'4S': 4,
              '3D': 3,'3H': 3,'3C': 3,'3S': 3,
              '2D': 2,'2H': 2,'2C': 2,'2S': 2,}

List = ['AD','AH','AC','AS',
            'KD','KH','KC','KS',
            'QD','QH','QC','QS', 
            'JD','JH','JC','JS',
            '10D','10H','10C','10S',
            '9D','9H','9C','9S',
            '8D','8H','8C','8S',
            '7D','7H','7C','7S',
            '6D','6H','6C','6S',
            '5D','5H','5C','5S',
            '4D','4H','4C','4S',
            '3D','3H','3C','3S',
            '2D','2H','2C','2S',]

def want2play():
    Hit2Play = input(" Hit 'y' to begin your game of 21): ")
    print ("")
    return Hit2Play

def deckCheck(DECK):
    print (DECK)
    print("There are:",len(DECK),"cards in the deck.") 
    if len(DECK) < 20:
        DECK = shuffleDeck() 
        return DECK
    else:
        return DECK

def openingDeal(DECK):
    PHAND = [] 
    DHAND = [] 
    DHANDT = [] 
    PHAND, DECK  = dealOneCard(PHAND, DECK) 
    DHAND, DECK = dealOneCard(DHAND, DECK)
    DHANDT.append(DHAND[0]) 
    PHAND, DECK  = dealOneCard(PHAND, DECK)
    DHAND, DECK = dealOneCard(DHAND, DECK)
    DHANDT.append("back of card")
    PPOINTS = scoreHAND(PHAND)     
    printScores_0(PPOINTS, PHAND, DHANDT)
    return PHAND, DHAND, DHANDT, DECK

def pLoop(PHAND, DHAND, DHANDT, DECK):
    while scoreHAND(PHAND) < 21:
        hitorhold = input('Do you want to hit or hold?: ')
        if hitorhold == 'hit':
            dealOneCard(PHAND, DECK)
            printScores_0(scoreHAND(PHAND), PHAND, DHANDT)
        elif hitorhold == 'hold':
            print('Player holds')
            printScores_0(scoreHAND(PHAND), PHAND, DHANDT)
            break
    return PHAND, DHAND, DECK

def dLoop(PHAND, DHAND, DECK):
    printScores_1(scoreHAND(PHAND), scoreHAND(DHAND), PHAND, DHAND)

    if scoreHAND(DHAND) < 18 or scoreHAND(DHAND) < 21 or scoreHAND(DHAND) < scoreHAND(PHAND) or scoreHAND(DHAND) < 21 or scoreHAND(PHAND) < 22:
        dealOneCard(DHAND, DECK)
        printScores_1(scoreHAND(PHAND), scoreHAND(DHAND), PHAND, DHAND)
        return scoreHAND(PHAND), scoreHAND(DHAND), PHAND, DHAND
    else:
        return scoreHAND(PHAND), scoreHAND(DHAND), PHAND, DHAND


def checkScore(pWin, dWin, PPOINTS, DPOINTS):
    if DPOINTS > PPOINTS and DPOINTS < 22:
        dWin += 1
        print (' ')
        print ("Dealer Win")
        return pWin, dWin

    elif PPOINTS == DPOINTS and PPOINTS < 21:
        dWin += 1
        print (' ')
        print ("Dealer Win")
        return pWin, dWin

    elif PPOINTS > 21 and DPOINTS < 21:
            dWin += 1
            print(' ')
            print("Dealer Win")
            return pWin, dWin

    elif PPOINTS < 22 and DPOINTS > 21:
            pWin += 1
            print (' ')
            print ("Player Win")
            return pWin, dWin

    elif PPOINTS > 21 and DPOINTS > 21:
            print (' ')
            print ("Tie.")
            return pWin, dWin

    elif PPOINTS == 21 and DPOINTS == 21:
            print(' ')
            print("Tie.")
            return pWin, dWin

def dealOneCard(HAND,DECK):
    theCard = DECK.pop(0)
    HAND.append(theCard) 
    return HAND, DECK

def shuffleDeck():
    CardPile = len(List)
    random.shuffle(List)
    return List

def scoreHAND(HAND):
    points = addScore(HAND) 
    aceCount=0
    if points > 21:
        aceCount += HAND.count('AS')
        aceCount += HAND.count('AH')
        aceCount += HAND.count('AC')
        aceCount += HAND.count('AD')
        while points > 21 and aceCount > 0:
            points -= 10
            aceCount -= 1
        return points
    else:
        return points

def addScore(HAND):
    tempScore = 0
    for i in HAND:
        tempScore += CARDPOINTS[i]
    return tempScore 

def printScores_0(POINTS, HAND, HAND1):
    print("Player's cards: ", HAND, "Player's hand score: ", POINTS)
    print("Dealer's cards: ", HAND1)

def printScores_1(PPOINTS, DPOINTS, PHAND, DHAND):
    print("Player's cards: ", PHAND, "Player's hand score: ", PPOINTS)
    print("Dealer's cards: ", DHAND, "Dealer's hand score: ", DPOINTS)

def main():
    DECK = shuffleDeck()
    pWin = 0
    dWin = 0
    while True:
        Hit2Play = want2play()
        if Hit2Play == 'y':
            DECK = deckCheck(DECK)
            PHAND, DHAND, DHANDT, DECK = openingDeal(DECK)
            PHAND, DHAND, DECK = pLoop(PHAND, DHAND, DHANDT, DECK)
            PPOINTS, DPOINTS, PHAND, DHAND = dLoop(PHAND, DHAND, DECK)
            pWin, dWin = checkScore(pWin, dWin, PPOINTS, DPOINTS)
            print("")
            print("Player's Wins:", pWin, "Dealer's Wins:",dWin)
            print("")

        else:
            print("Player's Wins:", pWin, "Dealer's Wins:",dWin)

            break
main()

【问题讨论】:

  • PEP-8 建议应为常量保留 ALL_CAPS。
  • 你确定这是堆栈跟踪吗?它应该追溯到迭代失败的确切点,该点比您显示的行更靠近调用堆栈。从堆栈跟踪的底部,查看每一行的代码,并问自己这个变量是如何变成None 的。如果您需要更多信息,请四处打印。
  • 不管你在下面得到什么帮助,在你发送你的程序后,你应该把这段损坏的代码复制一份,并学习使用 pdb,python 调试器! stackoverflow.com/questions/1623039/python-debugging-tips --- docs.python.org/2/library/pdb.html
  • 如果某个答案对您有帮助,您应该接受它作为解决方案。

标签: python


【解决方案1】:

我在这段代码中看到的唯一问题是在 checkScore() 函数中,每个 if 语句都返回相同的内容,但在 ifs 之外没有返回。如果您错过了极端情况或其他情况,那么这将引发错误。我建议移动线路

return pwin, dwin

在 if, elif 块之外。如果这不能解决您的问题,请尝试修改 dloop 函数;只有当函数返回 None 时才会发生您收到的错误。

【讨论】:

  • 你能给我举个例子来说明你的意思吗?
  • 我做了一个快速测试,遇到了同样的事情:checkScore 有时会返回None。我看不到 dLoop 这样做的任何方法,所以我无法将发布的代码与生成 OP 原始错误的代码相协调。
  • Wattel,checkScore 中没有最终的else:,所以它有时会返回None。添加else:
  • 是 else: 你认为的问题吗?
【解决方案2】:

这是最终的代码结果!有没有人发现任何问题?

##21 Card Game 
##Wattel
##2016 Spring

from random import *
import random
from random import shuffle, randint

CARDPOINTS = {'AD': 11,'AH': 11,'AC': 11,'AS': 11,
              'KD': 10,'KH': 10,'KC': 10,'KS':10,
              'QD': 10,'QH': 10,'QC': 10,'QS': 10, 
              'JD': 10,'JH': 10,'JC': 10,'JS': 10,
              '10D': 10,'10H': 10,'10C': 10,'10S': 10,
              '9D': 9,'9H': 9,'9C': 9,'9S': 9,
              '8D': 8,'8H': 8,'8C': 8,'8S': 8,
              '7D': 7,'7H': 7,'7C': 7,'7S': 7,
              '6D': 6,'6H': 6,'6C': 6,'6S': 6,
              '5D': 5,'5H': 5,'5C': 5,'5S': 5,
              '4D': 4,'4H': 4,'4C': 4,'4S': 4,
              '3D': 3,'3H': 3,'3C': 3,'3S': 3,
              '2D': 2,'2H': 2,'2C': 2,'2S': 2,}

def shuffleDeck():

    List = ['AD','AH','AC','AS',
            'KD','KH','KC','KS',
            'QD','QH','QC','QS', 
            'JD','JH','JC','JS',
            '10D','10H','10C','10S',
            '9D','9H','9C','9S',
            '8D','8H','8C','8S',
            '7D','7H','7C','7S',
            '6D','6H','6C','6S',
            '5D','5H','5C','5S',
            '4D','4H','4C','4S',
            '3D','3H','3C','3S',
            '2D','2H','2C','2S',]
    CardPile = len(List)
    random.shuffle(List)
    return List

def want2play():
    Hit2Play = input(" Hit 'y' to begin your game of 21): ")
    print ("")
    return Hit2Play

def deckCheck(DECK):
    print (DECK)
    print("There are:",len(DECK),"cards in the deck.") 
    if len(DECK) < 20:
        DECK = shuffleDeck() 
        return DECK
    else:
        return DECK

def openingDeal(DECK):
    PHAND = [] 
    DHAND = [] 
    DHANDT = [] 
    PHAND, DECK  = dealOneCard(PHAND, DECK) 
    DHAND, DECK = dealOneCard(DHAND, DECK)
    DHANDT.append(DHAND[0]) 
    PHAND, DECK  = dealOneCard(PHAND, DECK)
    DHAND, DECK = dealOneCard(DHAND, DECK)
    DHANDT.append("back of card")
    PPOINTS = scoreHAND(PHAND)     
    printScores_0(PPOINTS, PHAND, DHANDT)
    return PHAND, DHAND, DHANDT, DECK

def pLoop(PHAND, DHAND, DHANDT, DECK):
    while scoreHAND(PHAND) < 21:
        hitorhold = input('Do you want to hit or hold?: ')
        if hitorhold == 'hit':
            dealOneCard(PHAND, DECK)
            printScores_0(scoreHAND(PHAND), PHAND, DHANDT)
        elif hitorhold == 'hold':
            print('Player holds')
            printScores_0(scoreHAND(PHAND), PHAND, DHANDT)
            break
    return PHAND, DHAND, DECK

def dLoop(PHAND, DHAND, DECK):
    printScores_1(scoreHAND(PHAND), scoreHAND(DHAND), PHAND, DHAND)

    if scoreHAND(DHAND) < 21 or scoreHAND(DHAND) < 21 or scoreHAND(DHAND) < scoreHAND(PHAND) or scoreHAND(DHAND) < 21 or scoreHAND(PHAND) < 22:
        dealOneCard(DHAND, DECK)
        printScores_1(scoreHAND(PHAND), scoreHAND(DHAND), PHAND, DHAND)
        return scoreHAND(PHAND), scoreHAND(DHAND), PHAND, DHAND
    else:
        return scoreHAND(PHAND), scoreHAND(DHAND), PHAND, DHAND


def checkScore(pWin, dWin, PPOINTS, DPOINTS):
    if DPOINTS > PPOINTS and DPOINTS < 22:
        dWin += 1
        print (' ')
        print ("Dealer Win")
        return pWin, dWin

    elif PPOINTS == DPOINTS and PPOINTS < 21:
        dWin += 1
        print (' ')
        print ("Dealer Win")
        return pWin, dWin

    elif PPOINTS > 21 and DPOINTS < 21:
        dWin += 1
        print(' ')
        print("Dealer Win")
        return pWin, dWin

    elif PPOINTS < 22 and DPOINTS > 21:
        pWin += 1
        print (' ')
        print ("Player Win")
        return pWin, dWin

    elif PPOINTS > 21 and DPOINTS > 21:
        print (' ')
        print ("Tie.")
        return pWin, dWin

    else:
        PPOINTS == 21 and DPOINTS == 21
        print(' ')
        print("Tie.")
        return pWin, dWin

def dealOneCard(HAND,DECK):
    theCard = DECK.pop(0)
    HAND.append(theCard) 
    return HAND, DECK

def scoreHAND(HAND):
    points = addScore(HAND) 
    aceCount=0
    if points > 21:
        aceCount += HAND.count('AS')
        aceCount += HAND.count('AH')
        aceCount += HAND.count('AC')
        aceCount += HAND.count('AD')
        while points > 21 and aceCount > 0:
            points -= 10
            aceCount -= 1
        return points
    else:
        return points

def addScore(HAND):
    tempScore = 0
    for i in HAND:
        tempScore += CARDPOINTS[i]
    return tempScore 

def printScores_0(POINTS, HAND, HAND1):
    print("Player's cards: ", HAND, "Player's hand score: ", POINTS)
    print("Dealer's cards: ", HAND1)

def printScores_1(PPOINTS, DPOINTS, PHAND, DHAND):
    print("Player's cards: ", PHAND, "Player's hand score: ", PPOINTS)
    print("Dealer's cards: ", DHAND, "Dealer's hand score: ", DPOINTS)

def main():
    DECK = shuffleDeck()
    pWin = 0
    dWin = 0
    while True:
        Hit2Play = want2play()
        if Hit2Play == 'y':
            DECK = deckCheck(DECK)
            PHAND, DHAND, DHANDT, DECK = openingDeal(DECK)
            PHAND, DHAND, DECK = pLoop(PHAND, DHAND, DHANDT, DECK)
            PPOINTS, DPOINTS, PHAND, DHAND = dLoop(PHAND, DHAND, DECK)
            pWin, dWin = checkScore(pWin, dWin, PPOINTS, DPOINTS)
            print("")
            print("Player's Wins:", pWin, "Dealer's Wins:",dWin)
            print("")

        else:
            print("Player's Wins:", pWin, "Dealer's Wins:",dWin)

            break
main()

【讨论】:

    【解决方案3】:

    我猜你在新代码中打错字了,并且

        else:
            PPOINTS == 21 and DPOINTS == 21
            print(' ')
            print("Tie.")
            return pWin, dWin
    

    应该是

        elif PPOINTS == 21 and DPOINTS == 21:
            print(' ')
            print("Tie.")
            return pWin, dWin
    

    如果是这样,我写了一个这样的快速测试框架:

    results = [[''] * 25 for _ in range(25)]
    
    for dp in range(25):
        for pp in range(25):
            res = checkScore(0, 0, pp, dp)
            if res is None:
                results[dp][pp] = 'N'
            else:
                p, d = res
                results[dp][pp] = ["=+","-="][d][p]
    
    results.reverse()    # flip bottom-to-top
    print("\n".join("".join(row) for row in results))
    

    给出(添加了标签):编辑:我的得分倒退了:

          ++++++++++++++++++++++===
          ++++++++++++++++++++++===
          ++++++++++++++++++++++===
    D     ---------------------=NNN
    e  20 ---------------------N---
    a     --------------------NN---       +  player wins
    l     -------------------NNN---       =  player ties
    e     ------------------NNNN---       -  player loses
    r     -----------------NNNNN---
       15 ----------------NNNNNN---
    P     ---------------NNNNNNN---       N  game crashes because
    o     --------------NNNNNNNN---          checkScore does not
    i     -------------NNNNNNNNN---          handle this combination
    n     ------------NNNNNNNNNN---          of inputs
    t  10 -----------NNNNNNNNNNN---
    s     ----------NNNNNNNNNNNN---
          ---------NNNNNNNNNNNNN---
          --------NNNNNNNNNNNNNN---
          -------NNNNNNNNNNNNNNN---
        5 ------NNNNNNNNNNNNNNNN---
          -----NNNNNNNNNNNNNNNNN---
          ----NNNNNNNNNNNNNNNNNN---
          ---NNNNNNNNNNNNNNNNNNN---
          --NNNNNNNNNNNNNNNNNNNN---
        0 -NNNNNNNNNNNNNNNNNNNNN---
    
          0    5    1    1    2
                    0    5    0
    
               Player Points
    

    我在那里看到很多 Ns。


    编辑2:解决办法:

    上面的图表应该可以很容易地看到所涉及的几何区域;我们只需要重写checkScore 即可正确处理它们:

    def check_score(player_wins, dealer_wins, player_pts, dealer_pts):
        if dealer_pts > 21:
            if player_pts > 21:
                # no-one wins (top right square)
                print("\nTie")
                return player_wins, dealer_wins
            else:
                # player wins (top left rectangle)
                print("\nPlayer wins")
                return player_wins + 1, dealer_wins
        else:
            if player_pts > 21:
                # player loses (bottom right rectangle)
                print("\nDealer wins")
                return player_wins, dealer_wins + 1
            elif dealer_pts >= player_pts:
                # player loses (top triangle)
                print("\nDealer wins")
                return player_wins, dealer_wins + 1
            else:
                # player wins (bottom triangle)
                print("\nPlayer wins")
                return player_wins + 1, dealer_wins
    

    重新测试给了我们

    ++++++++++++++++++++++===
    ++++++++++++++++++++++===
    ++++++++++++++++++++++===
    -------------------------
    ---------------------+---
    --------------------++---      Problem solved!
    -------------------+++---
    ------------------++++---
    -----------------+++++---
    ----------------++++++---
    ---------------+++++++---
    --------------++++++++---
    -------------+++++++++---
    ------------++++++++++---
    -----------+++++++++++---
    ----------++++++++++++---
    ---------+++++++++++++---
    --------++++++++++++++---
    -------+++++++++++++++---
    ------++++++++++++++++---
    -----+++++++++++++++++---
    ----++++++++++++++++++---
    ---+++++++++++++++++++---
    --++++++++++++++++++++---
    -+++++++++++++++++++++---
    

    【讨论】:

      【解决方案4】:

      为了比较,我写了一个面向对象的版本。希望你能从中学到很多东西;-)

      from random import shuffle
      
      LOSE, TIE, WIN = -1, 0, 1
      
      def get_yn(prompt, error_message=None, yes_values={'y','yes',''}, no_values={'n','no'}):
          """
          Prompt for input until a yes_value or no_value is entered.
          Return True for a yes_value or False for a no_value
          """
          while True:
              response = input(prompt).strip().lower()
              if response in yes_values:
                  return True
              elif response in no_values:
                  return False
              elif error_message is not None:
                  print(error_message)
      
      class Deck:
          SUITS  = ('D', 'H', 'C', 'S')
          FACES  = ('2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A')
          POINTS = ( 2,   3,   4,   5,   6,   7,   8,   9,   10,  10,  10,  10,  11 )
      
          def __init__(self):
              self.reset()
      
          def freshen(self):
              if len(self.cards) < 20:
                  self.reset()
      
          def reset(self):
              self.cards = list(self.CARD_VALUES)
              shuffle(self.cards)
      
          def deal_to(self, hand):
              card = self.cards.pop()
              hand.cards.append(card)
      
      # Back-patch because we cannot refer to Deck class variables until Deck is fully defined
      Deck.CARD_VALUES = {f+s:p for f,p in zip(Deck.FACES, Deck.POINTS) for s in Deck.SUITS}
      
      class Hand:
          def __init__(self):
              self.cards = []
      
          @property
          def points(self):
              # get sum of cards values, counting aces as 11
              card_value = Deck.CARD_VALUES.__getitem__
              total = sum(card_value(card) for card in self.cards)
              if total > 21:
                  # Aces can also be counted as 1;
                  #   if total is too high, try to get it <= 21
                  max_aces = sum(card[0] == 'A' for card in self.cards)
                  use_aces = (total - 12) // 10
                  total -= 10 * min(use_aces, max_aces)
              return total
      
          def __str__(self):
              return "{}  ({} points)".format(" ".join(self.cards), self.points)
      
          def dealer_first_hand(self):
              # alternate __str__ for use while dealer's second card is hidden
              return "{} ??".format(self.cards[0])
      
      def show_hands(player, dealer, first_hand=False):
          print("Player hand: {}".format(player))
          print("Dealer hand: {}\n".format(dealer.dealer_first_hand() if first_hand else dealer))
      
      class TwentyOne:
          def __init__(self):
              self.deck = Deck()
      
          @staticmethod
          def result(player_pts, dealer_pts):
              if dealer_pts > 21:
                  if player_pts > 21:
                      # no-one wins (top right square)
                      print("\nTie")
                      return TIE
                  else:
                      # player wins (top left rectangle)
                      print("\nPlayer wins")
                      return WIN
              else:
                  if player_pts > 21:
                      # player loses (bottom right rectangle)
                      print("\nDealer wins")
                      return LOSE
                  elif dealer_pts >= player_pts:
                      # player loses (top triangle)
                      print("\nDealer wins")
                      return LOSE
                  else:
                      # player wins (bottom triangle)
                      print("\nPlayer wins")
                      return WIN
      
          def play(self):
              self.deck.freshen()
              player = Hand()
              dealer = Hand()
              # opening deal
              self.deck.deal_to(player)
              self.deck.deal_to(dealer)
              self.deck.deal_to(player)
              self.deck.deal_to(dealer)
              # player loop
              while player.points < 21:
                  show_hands(player, dealer, True)
                  if get_yn("Do you want to take another card? [Y/n] "):
                      self.deck.deal_to(player)
                  else:
                      print("Player holds\n")
                      break
              # dealer loop
              show_hands(player, dealer)
              while dealer.points < 17:
                  self.deck.deal_to(dealer)
                  show_hands(player, dealer)
              # tally the result
              return self.result(player.points, dealer.points)
      
      def main():
          game   = TwentyOne()
          wins   = 0
          losses = 0
          while True:
              result  = game.play()
              wins   += (result == WIN)
              losses += (result == LOSE)
              print("Player won {}, dealer won {}\n".format(wins, losses))
              if not get_yn("Play again? [Y/n] "): break
      
      if __name__ == "__main__":
          main()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-18
        • 2021-03-29
        • 2023-03-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多