为什么在我的Python二十一个纸牌游戏中发生此错误?

问题描述:

以下是错误:为什么在我的Python二十一个纸牌游戏中发生此错误?

Traceback (most recent call last): File "C:/Users/Wattel/Desktop/21 21 21.py", line 177, in main() File "C:/Users/Wattel/Desktop/21 21 21.py", line 167, in main PPOINTS, DPOINTS, PHAND, DHAND = dLoop(PHAND, DHAND, DECK) TypeError: 'NoneType' object is not iterable

我知道它有事情做与此代码,但不能找出问题到底是什么:

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() 
+0

PEP-8建议ALL_CAPS应该为常量保留。 –

+0

你确定这是堆栈跟踪?它应该追溯到迭代失败的位置,这个位置比调用的线路更靠下调用堆栈。从堆栈跟踪的底部,查看每行的代码,并问自己该变量是如何变成'None'的。如果您需要更多信息,散点图会打印出来。 – tdelaney

+0

无论您在下面给出的帮助如何,在您发送程序之后,您应该获取此破解代码的副本,并学习使用pdb,python调试器! http://*.com/questions/1623039/python-debugging-tips --- https://docs.python.org/2/library/pdb.html – pyInTheSky

我在代码中看到的唯一问题是在checkScore()函数中,每个if语句都返回相同的东西,但没有返回o如果是。如果你错过了一个角落案件或其他事情,那么这将会引发错误。我建议移动线

return pwin, dwin 

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

+0

你能告诉我一个你是什么意思的例子吗? – Wattel

+1

我做了一个快速测试,遇到了同样的情况:'checkScore'有时会返回'None'。我看不到任何'dLoop'这样做的方式,所以我无法将发布的代码与生成OP原始错误的代码进行协调。 –

+1

Wattel,在checkScore中没有最终的'else:',所以它有时返回'None'。添加一个'else:' –

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

##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() 

我相信在您的新密码输入有误,并

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! 
-------------------+++--- 
------------------++++--- 
-----------------+++++--- 
----------------++++++--- 
---------------+++++++--- 
--------------++++++++--- 
-------------+++++++++--- 
------------++++++++++--- 
-----------+++++++++++--- 
----------++++++++++++--- 
---------+++++++++++++--- 
--------++++++++++++++--- 
-------+++++++++++++++--- 
------++++++++++++++++--- 
-----+++++++++++++++++--- 
----++++++++++++++++++--- 
---+++++++++++++++++++--- 
--++++++++++++++++++++--- 
-+++++++++++++++++++++--- 

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

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