Tic Tac Toe in Python

This notebook contains a Python implementation of the Tic Tac Toe game.

class Player:
    def __init__(self, name, symbol):
        self.name = name
        self.symbol = symbol

class EnhancedPlayer(Player):
    def __init__(self, name, symbol):
        super().__init__(name, symbol)
        self.wins = 0

    def add_win(self):
        self.wins += 1
        print(f"🏆 {self.name} now has {self.wins} wins!")

class Board:
    def __init__(self):
        self.grid = [" "] * 9
        self.move_count = 0

    def display(self):
        print("\n")
        print(" " + self.grid[0] + " | " + self.grid[1] + " | " + self.grid[2])
        print("---+---+---")
        print(" " + self.grid[3] + " | " + self.grid[4] + " | " + self.grid[5])
        print("---+---+---")
        print(" " + self.grid[6] + " | " + self.grid[7] + " | " + self.grid[8])
        print("\n")

    def display_reference(self):
        reference = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
        print("Board positions:\n")
        print(" " + reference[0] + " | " + reference[1] + " | " + reference[2])
        print("---+---+---")
        print(" " + reference[3] + " | " + reference[4] + " | " + reference[5])
        print("---+---+---")
        print(" " + reference[6] + " | " + reference[7] + " | " + reference[8])
        print("\n")

    def reset(self):
        self.grid = [" "] * 9
        self.move_count = 0
        print("🔄 Board has been reset!")

    def is_full(self):
        return " " not in self.grid

    def make_move(self, position, symbol):
        index = position - 1
        if index < 0 or index > 8:
            print("❌ Invalid position. Choose a number between 1 and 9.")
            return False
        if self.grid[index] != " ":
            print("❌ That spot is already taken. Try again.")
            return False
        self.grid[index] = symbol
        self.move_count += 1
        return True

    def check_winner(self, symbol):
        win_combinations = [
            [0, 1, 2], [3, 4, 5], [6, 7, 8],  # Rows
            [0, 3, 6], [1, 4, 7], [2, 5, 8],  # Columns
            [0, 4, 8], [2, 4, 6]              # Diagonals
        ]
        for combo in win_combinations:
            if (self.grid[combo[0]] == symbol and
                self.grid[combo[1]] == symbol and
                self.grid[combo[2]] == symbol):
                return True
        return False

class TicTacToe:
    def __init__(self, player1, player2):
        self.board = Board()
        self.players = [player1, player2]
        self.current_player = player1
        self.game_over = False

    def switch_player(self):
        self.current_player = (
            self.players[1] if self.current_player == self.players[0] else self.players[0]
        )
        print(f"🔄 Now it's {self.current_player.name}'s turn!")

    def play(self):
        self.board.display_reference()
        self.board.display()
        while not self.game_over:
            try:
                position = int(input(f"{self.current_player.name} ({self.current_player.symbol}), choose a position (1-9): "))
            except ValueError:
                print("❌ Please enter a number between 1 and 9.")
                continue

            if self.board.make_move(position, self.current_player.symbol):
                self.board.display()

                if self.board.check_winner(self.current_player.symbol):
                    print(f"🎉 {self.current_player.name} ({self.current_player.symbol}) WINS!")
                    if isinstance(self.current_player, EnhancedPlayer):
                        self.current_player.add_win()
                    self.game_over = True
                elif self.board.is_full():
                    print("🤝 It's a tie!")
                    self.game_over = True
                else:
                    self.switch_player()

        self.ask_restart()

    def ask_restart(self):
        choice = input("🔁 Do you want to play again? (y/n): ").lower()
        if choice == "y":
            self.board.reset()
            self.game_over = False
            self.play()
        else:
            print("👋 Thanks for playing!")

# === RUN THE GAME ===
print("=== Welcome to Tic-Tac-Toe ===")
p1_name = input("Enter name for Player 1: ")
p2_name = input("Enter name for Player 2: ")
player1 = EnhancedPlayer(p1_name, "X")
player2 = EnhancedPlayer(p2_name, "O")
game = TicTacToe(player1, player2)
game.play()