You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 22:18:42