Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import math | |
| # Check winner | |
| def check_winner(board, player): | |
| wins = [[0,1,2],[3,4,5],[6,7,8], | |
| [0,3,6],[1,4,7],[2,5,8], | |
| [0,4,8],[2,4,6]] | |
| return any(board[a]==board[b]==board[c]==player for a,b,c in wins) | |
| # Check draw | |
| def is_full(board): | |
| return ' ' not in board | |
| # Minimax with alpha-beta pruning | |
| def minimax(board, is_max, alpha, beta): | |
| if check_winner(board,'O'): return 1 | |
| if check_winner(board,'X'): return -1 | |
| if is_full(board): return 0 | |
| if is_max: | |
| best = -math.inf | |
| for i in range(9): | |
| if board[i]==' ': | |
| board[i]='O' | |
| val = minimax(board, False, alpha, beta) | |
| board[i]=' ' | |
| best = max(best, val) | |
| alpha = max(alpha, val) | |
| if beta<=alpha: break | |
| return best | |
| else: | |
| best = math.inf | |
| for i in range(9): | |
| if board[i]==' ': | |
| board[i]='X' | |
| val = minimax(board, True, alpha, beta) | |
| board[i]=' ' | |
| best = min(best, val) | |
| beta = min(beta, val) | |
| if beta<=alpha: break | |
| return best | |
| # AI move | |
| def ai_move(board): | |
| best_score = -math.inf | |
| move = None | |
| for i in range(9): | |
| if board[i]==' ': | |
| board[i]='O' | |
| score = minimax(board, False, -math.inf, math.inf) | |
| board[i]=' ' | |
| if score > best_score: | |
| best_score = score | |
| move = i | |
| if move is not None: | |
| board[move]='O' | |
| return board | |
| # Player move | |
| def player_move(cell, board): | |
| board = board.copy() # work on a copy | |
| if board[cell] != ' ': | |
| return board, "โ Spot taken!", board | |
| board[cell] = 'X' | |
| if check_winner(board,'X'): | |
| return board, "๐ You win!", board | |
| if is_full(board): | |
| return board, "๐ค Draw!", board | |
| board = ai_move(board) | |
| if check_winner(board,'O'): | |
| return board, "๐ป AI wins!", board | |
| if is_full(board): | |
| return board, "๐ค Draw!", board | |
| return board, "Your move!", board | |
| # Reset board | |
| def reset(): | |
| new_board = [' ' for _ in range(9)] | |
| return new_board, "New Game! You are X.", new_board | |
| # Update buttons | |
| def update_buttons(board): | |
| return [board[i] if board[i] != ' ' else " " for i in range(9)] | |
| # Build GUI | |
| with gr.Blocks(css=""" | |
| .grid {display:grid;grid-template-columns:repeat(3,100px);grid-gap:5px;justify-content:center;} | |
| .grid button {height:100px;width:100px;font-size:2em;font-weight:bold;} | |
| """) as demo: | |
| gr.Markdown("<h1 style='text-align:center'>๐ฎ Tic Tac Toe AI</h1>") | |
| status = gr.Label("New Game! You are X.") | |
| board_state = gr.State([' ' for _ in range(9)]) # ๐ persistent board state | |
| with gr.Column(): | |
| game_buttons = [] | |
| with gr.Row(elem_classes="grid"): | |
| for i in range(9): | |
| btn = gr.Button(" ") | |
| game_buttons.append(btn) | |
| reset_btn = gr.Button("๐ Reset Game") | |
| # Wire buttons to player_move with state | |
| for idx, btn in enumerate(game_buttons): | |
| btn.click(player_move, | |
| inputs=[gr.Number(value=idx, visible=False), board_state], | |
| outputs=[gr.State(), status, board_state]) \ | |
| .then(update_buttons, inputs=board_state, outputs=game_buttons) | |
| # Reset game | |
| reset_btn.click(reset, outputs=[gr.State(), status, board_state]) \ | |
| .then(update_buttons, inputs=board_state, outputs=game_buttons) | |
| demo.launch() | |