Двигатель крестики-нолики на языке Python для глубокого обучения


Я ввожу палец двигателя "Тик-Так", который будет работать с более углубленным изучением. Я использую массив NumPy 3х3 поплавков для представления совету. +1.0 представляет собой х, -1.0 представляет собой O, и 0.0 представляет собой пустой квадрат.

Мне интересно конкретно:

  • Существует ли лучше/более подходящие для Python способ перечисления Х/О значения?
  • Существует ли более эффективный способ проверить, есть ли победитель?

И более обобщенно:

  • Есть ли в крестики-нолики вопросы я не задумался?
  • В каком стиле/вопросы читабельности мой код?

Вот код:

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)
        )


Комментарии