import gradio as gr import numpy as np # Game constants PLAYER = "X" AI = "O" EMPTY = "" def check_winner(board): # Standard Tic-Tac-Toe win conditions win_states = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], # Rows [0, 3, 6], [1, 4, 7], [2, 5, 8], # Cols [0, 4, 8], [2, 4, 6] # Diagonals ] for line in win_states: if board[line[0]] == board[line[1]] == board[line[2]] != EMPTY: return board[line[0]] if EMPTY not in board: return "Tie" return None def minimax(board, depth, is_maximizing): res = check_winner(board) if res == AI: return 10 - depth if res == PLAYER: return depth - 10 if res == "Tie": return 0 if is_maximizing: best_score = -float('inf') for i in range(9): if board[i] == EMPTY: board[i] = AI score = minimax(board, depth + 1, False) board[i] = EMPTY best_score = max(score, best_score) return best_score else: best_score = float('inf') for i in range(9): if board[i] == EMPTY: board[i] = PLAYER score = minimax(board, depth + 1, True) board[i] = EMPTY best_score = min(score, best_score) return best_score def ai_move(board): best_score = -float('inf') move = -1 for i in range(9): if board[i] == EMPTY: board[i] = AI score = minimax(board, 0, False) board[i] = EMPTY if score > best_score: best_score = score move = i return move def play_game(board, idx): # Convert state to list board = list(board) # Player Move if board[idx] == EMPTY: board[idx] = PLAYER else: return board, "Cell already taken!" # Check if Player won status = check_winner(board) if status: return board, f"Game Over: {status} wins!" if status != "Tie" else "It's a Tie!" # AI Move ai_idx = ai_move(board) if ai_idx != -1: board[ai_idx] = AI # Check if AI won status = check_winner(board) if status: return board, f"Game Over: {status} wins!" if status != "Tie" else "It's a Tie!" return board, "Your turn, Player X" def reset_game(): return [EMPTY] * 9, "New Game! You are X." # UI Construction with gr.Blocks(css=".square {height: 100px !important; font-size: 2rem !important;}") as demo: gr.Markdown("# 🤖 AI Tic-Tac-Toe") gr.Markdown("Try to beat the unbeatable Minimax AI!") board_state = gr.State([EMPTY] * 9) status_msg = gr.Textbox(value="Your turn, Player X", label="Status") with gr.Column(elem_id="board"): buttons = [] for i in range(3): with gr.Row(): for j in range(3): idx = i * 3 + j btn = gr.Button(value=EMPTY, elem_classes="square") buttons.append(btn) reset_btn = gr.Button("Reset Game", variant="primary") # Click Logic for i, btn in enumerate(buttons): btn.click( play_game, inputs=[board_state, gr.Number(i, visible=False)], outputs=[board_state, status_msg] ) # Update UI buttons when state changes board_state.change( lambda b: [gr.update(value=val) for val in b], inputs=board_state, outputs=buttons ) reset_btn.click(reset_game, outputs=[board_state, status_msg]) if __name__ == "__main__": demo.launch()