import gradio as gr import random class TicTacToe: def __init__(self): self.board = [' ' for _ in range(9)] self.current_player = 'X' self.game_over = False self.winner = None self.player_wins = 0 self.ai_wins = 0 self.ties = 0 def reset_game(self): self.board = [' ' for _ in range(9)] self.current_player = 'X' self.game_over = False self.winner = None def make_move(self, position): if self.board[position] == ' ' and not self.game_over: self.board[position] = self.current_player if self.check_winner(): self.game_over = True self.winner = self.current_player if self.current_player == 'X': self.player_wins += 1 else: self.ai_wins += 1 elif ' ' not in self.board: self.game_over = True self.winner = 'Tie' self.ties += 1 else: self.current_player = 'O' if self.current_player == 'X' else 'X' return True return False def check_winner(self): lines = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6] ] for line in lines: if self.board[line[0]] == self.board[line[1]] == self.board[line[2]] != ' ': return True return False def ai_move(self): move = self.find_best_move() if move is not None: self.make_move(move) def find_best_move(self): for i in range(9): if self.board[i] == ' ': self.board[i] = 'O' if self.check_winner(): self.board[i] = ' ' return i self.board[i] = ' ' for i in range(9): if self.board[i] == ' ': self.board[i] = 'X' if self.check_winner(): self.board[i] = ' ' return i self.board[i] = ' ' if self.board[4] == ' ': return 4 corners = [0, 2, 6, 8] available = [i for i in corners if self.board[i] == ' '] if available: return random.choice(available) empty = [i for i in range(9) if self.board[i] == ' '] return random.choice(empty) if empty else None game = TicTacToe() def make_player_move(position): if game.game_over: return update_display() + ("Game Over! Click 'New Game' to play again.",) if game.make_move(position): if game.game_over: return update_display() + (get_game_status(),) game.ai_move() return update_display() + (get_game_status(),) return update_display() + ("Invalid move! Try another cell.",) def new_game(): game.reset_game() return update_display() + ("New game started! You are ❌, make your move!",) def update_display(): return tuple( gr.update(value="❌" if c == 'X' else "β­•" if c == 'O' else "", variant="primary" if c == 'X' else "stop" if c == 'O' else "secondary", interactive=(c == ' ' and not game.game_over)) for c in game.board ) def get_game_status(): if game.game_over: if game.winner == 'X': return "πŸŽ‰ You Win! Congratulations!" elif game.winner == 'O': return "πŸ€– AI Wins! Try again!" return "🀝 It's a Tie!" return "Your turn!" if game.current_player == 'X' else "AI is thinking... πŸ€–" with gr.Blocks( theme=gr.themes.Soft(), title="🎯 Smart Tic-Tac-Toe vs AI", css=""" .game-button { height: 80px; font-size: 2em; } """ ) as demo: gr.Markdown("# 🎯 Smart Tic-Tac-Toe vs AI") gr.Markdown("### You are ❌, AI is β­• β€” Get 3 in a row to win!") with gr.Row(): with gr.Column(scale=2): with gr.Row(): btn0 = gr.Button("", elem_classes="game-button") btn1 = gr.Button("", elem_classes="game-button") btn2 = gr.Button("", elem_classes="game-button") with gr.Row(): btn3 = gr.Button("", elem_classes="game-button") btn4 = gr.Button("", elem_classes="game-button") btn5 = gr.Button("", elem_classes="game-button") with gr.Row(): btn6 = gr.Button("", elem_classes="game-button") btn7 = gr.Button("", elem_classes="game-button") btn8 = gr.Button("", elem_classes="game-button") new_game_btn = gr.Button("πŸ” New Game", variant="primary") status_display = gr.Textbox( label="Game Status", value="New game started! You are ❌, make your move!", lines=2, interactive=False ) with gr.Column(scale=1): gr.Markdown("### πŸ“Š Game Stats") player_wins_display = gr.Number(label="πŸ† Your Wins", value=0, interactive=False) ai_wins_display = gr.Number(label="πŸ€– AI Wins", value=0, interactive=False) ties_display = gr.Number(label="🀝 Ties", value=0, interactive=False) with gr.Accordion("πŸ’‘ Strategy Tips", open=False): gr.Markdown(""" - Take the center if available - Block your opponent’s winning move - Create multiple win paths - Think ahead β€” the AI does! """) buttons = [btn0, btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8] for i, btn in enumerate(buttons): btn.click(fn=lambda pos=i: make_player_move(pos), outputs=buttons + [status_display]) new_game_btn.click(fn=new_game, outputs=buttons + [status_display]) def update_stats(): return game.player_wins, game.ai_wins, game.ties for btn in buttons: btn.click(fn=update_stats, outputs=[player_wins_display, ai_wins_display, ties_display]) new_game_btn.click(fn=update_stats, outputs=[player_wins_display, ai_wins_display, ties_display]) # Required for Hugging Face Spaces model = demo # βœ… REQUIRED to launch on Hugging Face if __name__ == "__main__": demo.launch()