Python石头剪刀布代码MemoryPlayer仅返回随机出拳的问题排查
石头剪刀布MemoryPlayer类始终返回随机出拳的问题排查
问题背景
我是Python初学者,首次在Stack Overflow提问,若提问存在不规范之处还请谅解。我正在使用Python自主编写石头剪刀布游戏,代码中设计了可记录玩家上一轮出拳的电脑玩家类MemoryPlayer,但运行时该类始终只能返回random.choice生成的随机出拳结果,无法定位代码出错位置,完整代码如下:
moves = ['rock', 'paper', 'scissors'] class Player: def __init__(self): self.my_move = None self.their_move = None def learn(self, my_move, their_move): self.my_move = my_move self.their_move = their_move def beats(one, two): return ((one == 'rock' and two == 'scissors') or (one == 'scissors' and two == 'paper') or (one == 'paper' and two == 'rock')) class MemoryPlayer(Player): def move(self): if self.their_move in moves: return self.their_move else: return random.choice(moves) class Game: def __init__(self, p1, p2): self.p1 = p1 self.p2 = p2 self.scorep1 = 0 self.scorep2 = 0 # starting score of both players def play_round(self): firstmove = self.p1.move() secondmove = self.p2.move() print(f"Player 1: {firstmove} Player 2: {secondmove}") # prints move of Player 1 and Player 2 after each round if beats(firstmove, secondmove): self.scorep1 += 1 print(f"Player 1 Wins. Score: {self.scorep1}" f" to {self.scorep2}") elif beats(secondmove, firstmove): self.scorep2 += 1 print(f"Player 2 Wins. Score: {self.scorep2}" f" to {self.scorep1}") else: print(f"Boring - TIE. Score: {self.scorep1}" f" to {self.scorep2}") # uses beats function in if and else statement to define score increase # if player 1 move beats player 2 move and vice versa def play_game(self): print("Game start!") self.rounds = 3 for round in range(self.rounds): print(f"Round {round}:") self.play_round() print(f"Game over! Final score:\ Player 1: {self.scorep1}), Player 2: {self.scorep2}") # prints final secores for Player 1 and Player 2 if self.scorep1 > self.scorep2: print("Player 1 is Triumphant") # if player 1 score is greater than player 2 - prints winning statement elif self.scorep2 > self.scorep1: print("Player 2 is Triumphant") # if player 2 score is greater than player 1 - prints winning statement else: print("Boring - TIE") if __name__ == '__main__': game = Game(HumanPlayer(), MemoryPlayer()) # randomly chooses opposing NPC game.play_game()
问题根因
核心问题是play_round方法拿到双方出拳结果后,从未调用两个玩家实例的learn()方法更新出拳记录:
MemoryPlayer初始化时self.their_move默认值是None- 因为没有执行
learn()赋值,self.their_move永远是None,始终不满足if self.their_move in moves的判断条件 - 所以每次调用
move()都会走到else分支返回随机出拳
除此之外代码还有3个会直接导致运行报错的问题:
- 代码使用了
random.choice但没有在开头导入random模块 - 入口实例化时使用了
HumanPlayer类,但代码中没有定义该类 - 最终得分打印语句中多了一个多余的右括号,格式错误
修复方案
- 在代码最开头补充模块导入:
import random
- 补全
HumanPlayer类实现,放在Player类定义之后即可:
class HumanPlayer(Player): def move(self): while True: user_input = input("请出拳(输入rock/paper/scissors):").strip().lower() if user_input in moves: return user_input print("输入无效,请重新输入")
- 修改
play_round方法,在拿到双方出拳后立刻调用learn()方法记录本轮出拳,供下一轮使用:
def play_round(self): firstmove = self.p1.move() secondmove = self.p2.move() print(f"Player 1: {firstmove} Player 2: {secondmove}") # 记录本轮双方出拳 self.p1.learn(firstmove, secondmove) self.p2.learn(secondmove, firstmove) if beats(firstmove, secondmove): self.scorep1 += 1 print(f"Player 1 Wins. Score: {self.scorep1}" f" to {self.scorep2}") elif beats(secondmove, firstmove): self.scorep2 += 1 print(f"Player 2 Wins. Score: {self.scorep2}" f" to {self.scorep1}") else: print(f"Boring - TIE. Score: {self.scorep1}" f" to {self.scorep2}")
- 修正最终得分打印的格式错误,去掉多余的右括号:
print(f"Game over! Final score:\ Player 1: {self.scorep1}, Player 2: {self.scorep2}")
修复后第一轮MemoryPlayer因为没有历史记录会随机出拳,从第二轮开始就会按照设计逻辑返回你上一轮的出拳了。
内容的提问来源于stack exchange,提问作者Signaldistress95
相关产品推荐
相关产品推荐

