Refactor lab with Strategy classes

This commit is contained in:
Chris Proctor
2022-05-06 16:46:03 -04:00
parent f49e78c35f
commit 6ad2672bd3
6 changed files with 179 additions and 86 deletions

View File

@@ -2,47 +2,81 @@ class TTTGame:
"Models a tic-tac-toe game."
def __init__(self, playerX, playerO):
self.board = [None] * 9
self.turn_index = 0
self.state = self.get_initial_state()
self.players = {
'X': playerX,
'O': playerO,
}
def play_move(self, move):
"Updates the game's state by recording a move"
if not self.is_valid_move(move):
raise ValueError(f"Illegal move {move} with board {self.board}.")
self.board[move] = self.get_current_player_symbol()
self.turn_index += 1
def get_initial_state(self):
"Returns the game's initial state."
return {
"board": ['-', '-', '-', '-', '-', '-', '-', '-', '-'],
"player": "X",
}
def get_valid_moves(self):
def get_next_state(self, state, action):
"""Given a state and an action, returns the resulting state.
In the resulting state, the current player's symbol has been placed
in an empty board space, and it is the opposite player's turn.
"""
new_board = state["board"]
new_board[action] = state["player"]
if state["player"] == "O":
new_player = "X"
else:
new_player = "O"
return {
"board": new_board,
"player": new_player,
}
def get_actions(self, state):
"Returns a list of the indices of empty spaces"
return [index for index in range(9) if self.board[index] is None]
return [index for index in range(9) if state["board"][index] == '-']
def is_over(self):
"Checks whether the game is over."
return self.board_is_full() or self.check_winner('X') or self.check_winner('O')
def get_reward(self, state):
"""Determines the reward associated with reaching this state.
For tic-tac-toe, the two opponents each want a different game outcome. So
we set the reward for X winning to 1 and the reward for O winning to -1.
All other states (unfinished games and games which ended in a draw) are worth 0.
"""
if self.check_winner('X'):
return 1
elif self.check_winner('O'):
return -1
else:
return 0
def get_objective(self, state):
"""Returns a player's objective, or a function describing what a player wants.
This function should choose the best value from a list. In tic tac toe, the players
want opposite things, so we set X's objective to the built-in function `max`
(which chooses the largest number), and we set O's objective to the built-in function `min`.
"""
if state["player"] == 'X':
return max
elif state["player"] == 'O':
return min
else:
raise ValueError(f"Unrecognized player {state['player']}")
def play_action(self, action):
"Plays a move, updating the game's state."
self.state = self.get_next_state(self.state, action)
def is_valid_move(self, move):
"Checks whether a move is valid"
return move in self.get_valid_moves()
def get_current_player_symbol(self):
"Returns the symbol of the current player"
if self.turn_index % 2 == 0:
return 'X'
else:
return 'O'
def get_current_player(self):
"Returns the symbol of the current player and the current player"
return self.players[self.get_current_player_symbol()]
def is_over(self):
"Checks whether the game is over."
return self.board_is_full() or self.check_winner('X') or self.check_winner('O')
def board_is_full(self):
"Checks whether all the spaces in the board are occupied."
for space in self.board:
if space == None:
for space in self.state["board"]:
if space == '-':
return False
return True