首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python中的岩石剪刀抽象

Python中的岩石剪刀抽象
EN

Stack Overflow用户
提问于 2021-12-24 02:30:54
回答 1查看 260关注 0票数 0

我做了一个高级Python后端工程师访谈,涉及到实现一个摇滚剪刀游戏。结果不太好。他们的工程师说我在各地都有笨拙的执行。后来我做了一次升级,但仍然有一个问题让我感到困惑。他们希望我将游戏规则的最初实现改为更好的抽象。

我最初的实现是:

代码语言:javascript
运行
复制
def _outcome(self, player_move, ai_move):
    """Determine the outcome of current round.

    Paper beats (wraps) rock.
    Rock beats (blunts) scissors.
    Scissors beats (cuts) paper.

    Parameters
    ----------
    player_move : MoveChoice
        Player's move for current round.

    ai_move : MoveChoice
        AI's move for current round.

    Returns
    -------
    outcome : Outcome
        Outcome of the current round.
    """
    if player_move == 1 and ai_move == 2 or \
        player_move == 2 and ai_move == 3 or \
        player_move == 3 and ai_move == 1:
        return self.computer.name
    elif player_move == 1 and ai_move == 3 or \
        player_move == 2 and ai_move == 1 or \
        player_move == 3 and ai_move == 2:
        return self.player.name
    else:
        return 'Draw'

通过映射:

代码语言:javascript
运行
复制
MOVE_CHOICE = {
    1: 'rock',
    2: 'paper',
    3: 'scissors',
}

我在其他地方定义了一个role.Playerrole.Computer类。他们的批评是:

  • 使用字符串(玩家名称或“抽签”)来表示一轮的结果
  • 没有游戏规则的抽象,只有一对大的布尔表达式来测试所有组合1乘1。

他们的建议如下:

  • 造型动作(岩石、纸、剪刀)
  • 将圆形结果(赢、输、平局)建模为Enum
  • 将游戏规则建模为两个移动并返回结果的函数,或者将移动映射为它赢得的移动列表。

到目前为止,我已经为移动和结果创建了Enum:

代码语言:javascript
运行
复制
class MoveChoice(Enum):
    ROCK = auto()
    PAPER = auto()
    SCISSORS = auto()


class Outcome(Enum):
    WIN = auto()
    LOSE = auto()
    DRAW = auto()

但我很难按照他们的要求抽象游戏规则。我该怎么做?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-24 03:09:57

根据您展示的代码和他们给您的建议,我会这样做:

代码语言:javascript
运行
复制
from enum import Enum, auto

class MoveChoice(Enum):
    ROCK = auto()
    PAPER = auto()
    SCISSORS = auto()

class Outcome(Enum):
    WIN = auto()
    LOSE = auto()
    DRAW = auto()

WIN_MAPPING = {
    MoveChoice.ROCK: MoveChoice.SCISSORS,
    MoveChoice.SCISSORS: MoveChoice.PAPER,
    MoveChoice.PAPER: MoveChoice.ROCK,
}

def outcome(player_move, ai_move):
    if player_move == ai_move:
        return Outcome.DRAW
    elif WIN_MAPPING[player_move] == ai_move:
        return Outcome.WIN
    else:
        return Outcome.LOSE

请注意,我已经将您的方法更改为一个函数。这不是关于总体程序结构的建议,它只是将逻辑描述为一个更独立的例子。

正如卢克·纳尔逊在评论中指出的那样,面试官建议win映射每个移动到它要执行的移动列表。我错过了这个细节。虽然它在摇滚剪刀中没有任何实际的区别,但它更具有普遍性,如果他们要求您将规则集扩展到类似石纸剪刀蜥蜴斯波克的内容,则会更容易。

映射的唯一变化是将每个值转换为一个单一元素列表:

代码语言:javascript
运行
复制
WIN_MAPPING = {
    MoveChoice.ROCK: [MoveChoice.SCISSORS],
    MoveChoice.SCISSORS: [MoveChoice.PAPER],
    MoveChoice.PAPER: [MoveChoice.ROCK],
}

然后,outcome函数将不必检查计算机的移动是否等于该值,而是必须检查它是否在值中(因为该值现在是一个列表)。

代码语言:javascript
运行
复制
def outcome(player_move, ai_move):
    if player_move == ai_move:
        return Outcome.DRAW
    # elif WIN_MAPPING[player_move] == ai_move:
    # Above line is replaced with:
    elif ai_move in WIN_MAPPING[player_move]:
        return Outcome.WIN
    else:
        return Outcome.LOSE
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70469062

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档