import gradio as gr import random class TicTacToe: def __init__(self): self.board = [" " for _ in range(9)] self.winning_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 ] self.human = "X" self.ai = "O" self.current_player = self.human def reset(self): self.board = [" " for _ in range(9)] self.current_player = self.human return self.board def make_move(self, position): if self.board[position] == " " and not self.is_game_over(): self.board[position] = self.current_player if self.current_player == self.human: self.current_player = self.ai # AI makes its move after human if not self.is_game_over(): ai_move = self.get_best_move() self.board[ai_move] = self.ai self.current_player = self.human return True return False def is_winner(self, player): for combo in self.winning_combinations: if all(self.board[i] == player for i in combo): return True return False def is_game_over(self): return self.is_winner(self.human) or self.is_winner(self.ai) or " " not in self.board def get_status(self): if self.is_winner(self.human): return "You win! 🎉" elif self.is_winner(self.ai): return "AI wins! 🤖" elif " " not in self.board: return "It's a tie! 🤝" return "Your turn!" def minimax(self, depth, is_maximizing): if self.is_winner(self.ai): return 1 if self.is_winner(self.human): return -1 if " " not in self.board: return 0 if is_maximizing: best_score = float('-inf') for i in range(9): if self.board[i] == " ": self.board[i] = self.ai score = self.minimax(depth + 1, False) self.board[i] = " " best_score = max(score, best_score) return best_score else: best_score = float('inf') for i in range(9): if self.board[i] == " ": self.board[i] = self.human score = self.minimax(depth + 1, True) self.board[i] = " " best_score = min(score, best_score) return best_score def get_best_move(self): best_score = float('-inf') best_move = None for i in range(9): if self.board[i] == " ": self.board[i] = self.ai score = self.minimax(0, False) self.board[i] = " " if score > best_score: best_score = score best_move = i return best_move game = TicTacToe() css = """ #game-container { max-width: 300px; margin: 0 auto; padding: 15px; } .board { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; background: #ff0000; padding: 4px; width: 240px; margin: 0 auto; } .cell { width: 100% !important; height: 75px !important; font-size: 24px !important; font-weight: bold !important; background: white !important; color: #0066cc !important; border: none !important; display: flex !important; align-items: center !important; justify-content: center !important; cursor: pointer !important; } .cell:hover { background: #f0f0f0 !important; } #message { text-align: center; margin: 15px 0; font-size: 18px; color: #333; } #reset-btn { background: #e74c3c !important; color: white !important; border: none !important; padding: 10px 20px !important; border-radius: 5px !important; cursor: pointer !important; margin: 10px auto !important; display: block !important; width: 120px !important; } """ def create_interface(): with gr.Blocks(css=css) as demo: with gr.Column(elem_id="game-container"): status = gr.Markdown("Your turn!", elem_id="message") with gr.Column(elem_classes=["board"]): cells = [] for i in range(9): cells.append(gr.Button(" ", elem_classes=["cell"])) reset = gr.Button("New Game", elem_id="reset-btn") def handle_click(idx): if game.make_move(idx): return { status: game.get_status(), **{cell: game.board[i] for i, cell in enumerate(cells)} } return {status: "Invalid move!"} def reset_game(): game.reset() return { status: "Your turn!", **{cell: " " for cell in cells} } for i, cell in enumerate(cells): cell.click( handle_click, inputs=[gr.State(i)], outputs=[status, *cells] ) reset.click( reset_game, outputs=[status, *cells] ) return demo demo = create_interface() demo.launch()