I did a senior python backend engineer interview. The result was not pretty. Their engineer said I'm having clumsy implementation all over the places. I did an upgrade afterwards but still have one confuses me. It's a paper-rock-scissors game. They would like me to change my original implementation about game rules of the game to better abstraction.
My original implementation is:
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'
with a mapping:
MOVE_CHOICE = {
1: 'rock',
2: 'paper',
3: 'scissors',
}
I have role.Player and role.Computer class seperately. Their words is:
- Use of strings (player name or “draw”) to represent the outcome of a round
- No abstraction of the game rules, just a couple of big Boolean expression testing all combinations 1 by 1
Their suggestions are:
- Modelling moves (rock, paper, scissors) as an Enum
- Modelling round outcomes (win, lose, draw) as an Enum
- Modelling the games rules as either a function that takes 2 moves and returns an outcome, or as a dict mapping a move to a list of move over which it wins
So far I created Enum Moves and Outcome:
class MoveChoice(Enum):
ROCK = auto()
PAPER = auto()
SCISSORS = auto()
class Outcome(Enum):
WIN = auto()
LOSE = auto()
DRAW = auto()
But having trouble abstract the game rules like they asked. Someone help me out please. Thank you.
CodePudding user response:
Based on the code you've shown and the recommendations they gave you, I would do something like this:
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
Note that I've changed your method to a function. This isn't a recommendation on overall program structure, it's just to present the logic as a more self-contained example.