3
\$\begingroup\$

I'm implementing a Tic Tac Toe engine that will work with deep learning. I'm using a 3x3 numpy array of floats to represent the board. +1.0 represents an X, -1.0 represents an O, and 0.0 represents an empty square.

I'm wondering specifically:

  • Is there a better/more Pythonic way to enumerate the X/O values?
  • Is there a more efficient way to test whether there is a winner?

And more generally:

  • Are there any Tic Tac Toe-related issues I'm not thinking about?
  • What style/readability issues does my code have?

Here's the code:

import numpy as np

class TicTacToe(object):
    DIM = 3
    ROWS = [
        # Rows
        [(0, 0), (0, 1), (0, 2)],
        [(1, 0), (1, 1), (1, 2)],
        [(2, 0), (2, 1), (2, 2)],
        # Cols
        [(0, 0), (1, 0), (2, 0)],
        [(0, 1), (1, 1), (2, 1)],
        [(0, 2), (1, 2), (2, 2)],
        # Diagonals
        [(0, 0), (1, 1), (2, 2)],
        [(0, 2), (1, 1), (2, 0)],
    ]

    class Move(object):
        X = 1.0
        O = -1.0

    class Win(object):
        X = 1.0
        O = -1.0
        DRAW = 0.0

    X_ROW = Move.X * DIM
    O_ROW = Move.O * DIM
    EMPTY = 0.0

    def __init__(self):
        self.board = np.zeros((TicTacToe.DIM, TicTacToe.DIM))

    def winner(self):
        for row in TicTacToe.ROWS:
            tot = sum([self.board[index] for index in row])
            if tot == TicTacToe.X_ROW:
                return TicTacToe.Win.X
            elif tot == TicTacToe.O_ROW:
                return TicTacToe.Win.O
        if TicTacToe.EMPTY in self.board:
            return None
        return TicTacToe.Win.DRAW

    def game_over(self):
        if self.winner() is None:
            return False
        return True

    def whose_turn(self, pretty=False):
        if pretty:
            return self.display_move(self.whose_turn(pretty=False))
        if self.board.sum():
            return TicTacToe.Move.O
        return TicTacToe.Move.X

    def make_move(self, row, col, display_board=True):
        if self.winner() is not None:
            raise Exception("Game is over. No more moves.")
        elif self.board[row, col] != self.EMPTY:
            raise Exception("That space is taken!")
        self.board[row, col] = self.whose_turn()
        if display_board:        
            self.print_board()

    def display_move(self, move):
        if move == TicTacToe.Move.X:
            return "X"
        elif move == TicTacToe.Move.O:
            return "O"
        return " "

    def print_board(self):
        move_chars = [self.display_move(move) for move in self.board.flatten()]
        print((
            " {} | {} | {} \n"
            "---|---|---\n"
            " {} | {} | {} \n"
            "---|---|---\n"
            " {} | {} | {} \n"
            ).format(*move_chars)
        )
\$\endgroup\$
  • \$\begingroup\$ This is an old question but tic tac toe is such a simple game that deep learning won't have any advantage compared to any other algorithm, I don't think it's a good use case for deep learning (Which doesn't make the question off-topic, but still) \$\endgroup\$ – IEatBagels Aug 15 '19 at 17:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.