generated from mwc/lab_tic_tac_toe
	Initial commit
This commit is contained in:
		
							
								
								
									
										61
									
								
								ttt/game.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								ttt/game.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
class TTTGame:
 | 
			
		||||
    "Models a tic-tac-toe game."
 | 
			
		||||
 | 
			
		||||
    def get_initial_state(self):
 | 
			
		||||
        "Returns the game's initial state."
 | 
			
		||||
        return {
 | 
			
		||||
            "board": ['-', '-', '-', '-', '-', '-', '-', '-', '-'],
 | 
			
		||||
            "player_x": True,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    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"].copy()
 | 
			
		||||
        new_board[action] = 'X' if state["player_x"] else 'O'
 | 
			
		||||
        return {
 | 
			
		||||
            "board": new_board,
 | 
			
		||||
            "player_x": not state["player_x"],
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def get_actions(self, state):
 | 
			
		||||
        "Returns a list of the indices of empty spaces"
 | 
			
		||||
        return [index for index in range(9) if state["board"][index] == '-']
 | 
			
		||||
 | 
			
		||||
    def is_over(self, state):
 | 
			
		||||
        "Checks whether the game is over."
 | 
			
		||||
        return self.board_is_full(state) or self.check_winner(state, 'X') or self.check_winner(state, '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(state, 'X'):
 | 
			
		||||
            return 1
 | 
			
		||||
        elif self.check_winner(state, '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`.
 | 
			
		||||
        """
 | 
			
		||||
        return max if state["player_x"] else min
 | 
			
		||||
 | 
			
		||||
    def board_is_full(self, state):
 | 
			
		||||
        "Checks whether all the spaces in the board are occupied."
 | 
			
		||||
        for space in state["board"]:
 | 
			
		||||
            if space == '-':
 | 
			
		||||
                return False
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def check_winner(self, state, symbol):
 | 
			
		||||
        "Checks whether the player with `symbol` has won the game."
 | 
			
		||||
        return False
 | 
			
		||||
							
								
								
									
										33
									
								
								ttt/player.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								ttt/player.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
from click import Choice, prompt
 | 
			
		||||
from strategy.random_strategy import RandomStrategy
 | 
			
		||||
from ttt.game import TTTGame
 | 
			
		||||
import random
 | 
			
		||||
 | 
			
		||||
class TTTHumanPlayer:
 | 
			
		||||
    "A human tic tac toe player."
 | 
			
		||||
 | 
			
		||||
    def __init__(self, name):
 | 
			
		||||
        "Sets up the player."
 | 
			
		||||
        self.name = name
 | 
			
		||||
        self.game = TTTGame()
 | 
			
		||||
 | 
			
		||||
    def choose_action(self, state):
 | 
			
		||||
        "Chooses an action by prompting the player for a choice."
 | 
			
		||||
        actions = self.game.get_actions(state)
 | 
			
		||||
        choices = Choice([str(action) for action in actions])
 | 
			
		||||
        action = int(prompt("> ", type=choices, show_choices=False))
 | 
			
		||||
        return action
 | 
			
		||||
 | 
			
		||||
class TTTComputerPlayer:
 | 
			
		||||
    "A computer tic tac toe player"
 | 
			
		||||
 | 
			
		||||
    def __init__(self, name):
 | 
			
		||||
        "Sets up the player."
 | 
			
		||||
        self.name = name
 | 
			
		||||
        self.strategy = RandomStrategy(TTTGame())
 | 
			
		||||
 | 
			
		||||
    def choose_action(self, state):
 | 
			
		||||
        "Chooses a random move from the moves available."
 | 
			
		||||
        action = self.strategy.choose_action(state)
 | 
			
		||||
        print(f"{self.name} chooses {action}.")
 | 
			
		||||
        return action
 | 
			
		||||
							
								
								
									
										75
									
								
								ttt/view.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								ttt/view.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
from ttt.game import TTTGame
 | 
			
		||||
import click
 | 
			
		||||
 | 
			
		||||
class TTTView:
 | 
			
		||||
    "Handles user interaction with a tic-tac-toe game."
 | 
			
		||||
    greeting = "Welcome to tic-tac-toe"
 | 
			
		||||
    goodbye = "Well, that's a wrap."
 | 
			
		||||
    divider = "---+---+---"
 | 
			
		||||
    x_color = "red"
 | 
			
		||||
    o_color = "blue"
 | 
			
		||||
    option_color = "bright_black"
 | 
			
		||||
 | 
			
		||||
    def __init__(self, playerX, playerO):
 | 
			
		||||
        self.game = TTTGame()
 | 
			
		||||
        self.players = {
 | 
			
		||||
            "X": playerX, 
 | 
			
		||||
            "O": playerO,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def greet(self):
 | 
			
		||||
        "Starts a new game by greeting the players."
 | 
			
		||||
        x_name = self.players['X'].name
 | 
			
		||||
        o_name = self.players['O'].name
 | 
			
		||||
        print(self.greeting)
 | 
			
		||||
        print(f"{x_name} will play as X.")
 | 
			
		||||
        print(f"{o_name} will play as O.")
 | 
			
		||||
 | 
			
		||||
    def get_action(self, state):
 | 
			
		||||
        "Shows the board and asks the current player for their choice of action."
 | 
			
		||||
        self.print_board(state)
 | 
			
		||||
        current_player_symbol = 'X' if state["player_x"] else 'O'
 | 
			
		||||
        player = self.players[current_player_symbol]
 | 
			
		||||
        print(f"{player.name}, it's your move.")
 | 
			
		||||
        return player.choose_action(state)
 | 
			
		||||
 | 
			
		||||
    def print_board(self, state):
 | 
			
		||||
        "Prints the current board, showing indices of available spaces"
 | 
			
		||||
        print(self.format_row(state, [0, 1, 2]))
 | 
			
		||||
        print(self.divider)
 | 
			
		||||
        print(self.format_row(state, [3, 4, 5]))
 | 
			
		||||
        print(self.divider)
 | 
			
		||||
        print(self.format_row(state, [6, 7, 8]))
 | 
			
		||||
 | 
			
		||||
    def format_row(self, state, indices):
 | 
			
		||||
        "Returns a string for one row in the board, like ' X | O | X '"
 | 
			
		||||
        spaces = [self.format_value(state, i) for i in indices]
 | 
			
		||||
        return f" {spaces[0]} | {spaces[1]} | {spaces[2]} "
 | 
			
		||||
 | 
			
		||||
    def format_value(self, state, index):
 | 
			
		||||
        """Formats the value for a single space on the board. 
 | 
			
		||||
        If the game board already has a symbol in that space, formats that value for the Terminal.
 | 
			
		||||
        If the space is empty, instead formats the index of the space. 
 | 
			
		||||
        """
 | 
			
		||||
        if state["board"][index] == 'X':
 | 
			
		||||
            return click.style('X', fg=self.x_color)
 | 
			
		||||
        elif state["board"][index] == 'O':
 | 
			
		||||
            return click.style('O', fg=self.o_color)
 | 
			
		||||
        else:
 | 
			
		||||
            return click.style(index, fg=self.option_color)
 | 
			
		||||
 | 
			
		||||
    def conclude(self, state):
 | 
			
		||||
        """Says goodbye.
 | 
			
		||||
        """
 | 
			
		||||
        self.print_board(state)
 | 
			
		||||
        if self.game.check_winner(state, 'X'):
 | 
			
		||||
            winner = self.players['X']
 | 
			
		||||
        elif self.game.check_winner(state, 'O'):
 | 
			
		||||
            winner = self.players['O']
 | 
			
		||||
        else:
 | 
			
		||||
            winner = None
 | 
			
		||||
        print(self.goodbye)
 | 
			
		||||
        if winner:        
 | 
			
		||||
            print(f"Congratulations to {winner.name}.")
 | 
			
		||||
        else:
 | 
			
		||||
            print("Nobody won this game.")
 | 
			
		||||
		Reference in New Issue
	
	Block a user