Console-based TicTacToe game in Python I created a console-based TicTacToe game in Python. So far, everything works as expected. I decided to keep the class static, because I figured there would be no use for multiple game states at once. Is there anything I can improve on?
class TicTacToe:
    &quot;&quot;&quot;Plays a 2-player TicTacToe Game.&quot;&quot;&quot;

    __curr_player = False  # simple bool player switch
    __game_matrix = [  # representation of game state
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
    ]

    @classmethod
    def play(cls):
        &quot;&quot;&quot;Play a single round.&quot;&quot;&quot;
        while not cls.__game_finished():

            # set current player
            player = 2 if cls.__curr_player else 1

            # get player move
            while 1:
                try:
                    print(f&quot;Player {player}'s turn.&quot;)
                    x = int(input(&quot;X: &quot;))
                    y = int(input(&quot;Y: &quot;))
                    if cls.__is_valid_field(x, y):
                        break
                    else:
                        print(&quot;Invalid field.&quot;)
                except ValueError:
                    print(&quot;Invalid Input.&quot;)

            cls.__update(x, y, player)
            print(&quot;Current game state: &quot;)
            cls.__display()

            # change player
            cls.__curr_player = not cls.__curr_player

        print(&quot;Game finished: &quot;)
        cls.__display()

        # reset state
        cls.__reset()

    @classmethod
    def __game_finished(cls):
        &quot;&quot;&quot;Returns True if one player has won or all fields are filled.&quot;&quot;&quot;
        # all filled?
        if all([value for line in cls.__game_matrix for value in line]):
            return True
        # horizontal win?
        if any(all([x == line[0] and x for x in line]) for line in cls.__game_matrix):
            return True
        # vertical win?
        if any(all([line[column] == cls.__game_matrix[0][column] and line[column] for line in cls.__game_matrix]) for column in range(3)):
            return True
        # diagonal win?
        if (cls.__game_matrix[0][0] == cls.__game_matrix[1][1] == cls.__game_matrix[2][2] != 0) or \
           (cls.__game_matrix[0][2] == cls.__game_matrix[1][1] == cls.__game_matrix[2][0] != 0):
            return True
        return False

    @classmethod
    def __is_valid_field(cls, x, y):
        &quot;&quot;&quot;Checks if field is already filled or out of range.&quot;&quot;&quot;
        if x &gt; 3 or x &lt; 1 or y &gt; 3 or y &lt; 1:
            return False
        return not cls.__game_matrix[y - 1][x - 1]

    @classmethod
    def __update(cls, x, y, player):
        &quot;&quot;&quot;Update game state.&quot;&quot;&quot;
        cls.__game_matrix[y - 1][x - 1] = player

    @classmethod
    def __display(cls):
        &quot;&quot;&quot;Displays current game state.&quot;&quot;&quot;
        for line in cls.__game_matrix:
            print(line)

    @classmethod
    def __reset(cls):
        &quot;&quot;&quot;Reset game state.&quot;&quot;&quot;
        cls.__curr_player = False
        cls.__game_matrix = [
            [0, 0, 0],
            [0, 0, 0],
            [0, 0, 0],
        ]


def main():
    TicTacToe.play()


if __name__ == &quot;__main__&quot;:
    main()
When i started the game, i found it pretty confusing as to what what coordinates should we input. I added an instructions method:

    @classmethod
    def __instructions(cls):
        print(
            'Welcome to TicTacToe\n'
            'Here is the board:\n'
            )
        cls.__display()
        print(
            'The coordinates start at top left\n'
            '(1, 1) (2, 1) (3, 1)\n'
            '(1, 2) (2, 2) (3, 2)\n'
            '(1, 3) (2, 3)  (3, 3)\n'
            )


I found having 0, 1, 2 on the board is pretty confusing. I replaced empty cells with a symbol, in this case -

    @classmethod
    def __display(cls):
        &quot;&quot;&quot;Displays current game state.&quot;&quot;&quot;
        for line in cls.__game_matrix:
            symbols = []
            for elem in line:
                if elem == 0:
                    symbols.append('-')
                else:
                    symbols.append(str(elem))
            print(' '.join(symbols))


I rearraged private methods before

I added a win annoncement to know who won:


print(&quot;Game finished: Player {} won!&quot;.format(player))

If you used a normal class you would not have needed

@classmethod
def __game_finished(cls):

but would have used the normal
def __game_finished(self):

less writing

Here is my code:
class TicTacToe:
    &quot;&quot;&quot;Plays a 2-player TicTacToe Game.&quot;&quot;&quot;

    __curr_player = False  # simple bool player switch
    __game_matrix = [  # representation of game state
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
    ]

    @classmethod
    def __game_finished(cls):
        &quot;&quot;&quot;Returns True if one player has won or all fields are filled.&quot;&quot;&quot;
        # all filled?
        if all([value for line in cls.__game_matrix for value in line]):
            return True
        # horizontal win?
        if any(all([x == line[0] and x for x in line]) for line in cls.__game_matrix):
            return True
        # vertical win?
        if any(all([line[column] == cls.__game_matrix[0][column] and line[column] for line in cls.__game_matrix]) for column in range(3)):
            return True
        # diagonal win?
        if (cls.__game_matrix[0][0] == cls.__game_matrix[1][1] == cls.__game_matrix[2][2] != 0) or \
           (cls.__game_matrix[0][2] == cls.__game_matrix[1][1] == cls.__game_matrix[2][0] != 0):
            return True
        return False

    @classmethod
    def __is_valid_field(cls, x, y):
        &quot;&quot;&quot;Checks if field is already filled or out of range.&quot;&quot;&quot;
        if x &gt; 3 or x &lt; 1 or y &gt; 3 or y &lt; 1:
            return False
        return not cls.__game_matrix[y - 1][x - 1]

    @classmethod
    def __update(cls, x, y, player):
        &quot;&quot;&quot;Update game state.&quot;&quot;&quot;
        cls.__game_matrix[y - 1][x - 1] = player

    @classmethod
    def __display(cls):
        &quot;&quot;&quot;Displays current game state.&quot;&quot;&quot;
        for line in cls.__game_matrix:
            symbols = []
            for elem in line:
                if elem == 0:
                    symbols.append('-')
                else:
                    symbols.append(str(elem))
            print(' '.join(symbols))

    @classmethod
    def __reset(cls):
        &quot;&quot;&quot;Reset game state.&quot;&quot;&quot;
        cls.__curr_player = False
        cls.__game_matrix = [
            ['-', '-', '-'],
            ['-', '-', '-'],
            ['-', '-', '-'],
        ]

    @classmethod
    def __instructions(cls):
        print(
            'Welcome to TicTacToe\n'
            'Here is the board:\n'
            )
        cls.__display()
        print(
            'The coordinates start at top left\n'
            '(1, 1) (2, 1) (3, 1)\n'
            '(1, 2) (2, 2) (3, 2)\n'
            '(1, 3) (2, 3)  (3, 3)\n'
            )

    @classmethod
    def play(cls):
        cls.__instructions()
        &quot;&quot;&quot;Play a single round.&quot;&quot;&quot;
        while not cls.__game_finished():

            # set current player
            player = 2 if cls.__curr_player else 1

            # get player move
            while 1:
                try:
                    print(f&quot;Player {player}'s turn.&quot;)
                    x = int(input(&quot;X: &quot;))
                    y = int(input(&quot;Y: &quot;))
                    if cls.__is_valid_field(x, y):
                        break
                    else:
                        print(&quot;Invalid field.&quot;)
                except ValueError:
                    print(&quot;Invalid Input.&quot;)

            cls.__update(x, y, player)
            print(&quot;Current game state: &quot;)
            cls.__display()

            # change player
            cls.__curr_player = not cls.__curr_player

        print(&quot;Game finished: Player {} won!&quot;.format(player))
        cls.__display()

        # reset state
        cls.__reset()

    


def main():
    TicTacToe.play()


if __name__ == &quot;__main__&quot;:
    main()

The code was well commented, broken down, easy to follow and clean!