import gradio as gr import random from typing import Dict import uuid 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 # Rest of your TicTacToe class remains the same... # (keeping all other methods identical) # Dictionary to store game instances for each session games: Dict[str, TicTacToe] = {} def get_game(session_id: str) -> TicTacToe: if session_id not in games: games[session_id] = TicTacToe() return games[session_id] css = """ # Your existing CSS remains the same """ def create_interface(): with gr.Blocks(css=css) as demo: session_id = gr.State(lambda: str(uuid.uuid4())) 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, session): game = get_game(session) 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(session): game = get_game(session) 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), session_id], outputs=[status, *cells] ) reset.click( reset_game, inputs=[session_id], outputs=[status, *cells] ) return demo demo = create_interface() demo.queue() # Enable queuing for multiple users demo.launch()