import numpy as np import gradio as gr class TicTacToeAI: def __init__(self): self.board = np.full((3, 3), "", dtype=str) self.human = "X" self.ai = "O" def is_winner(self, board, player): return any([ np.all(row == player) for row in board ]) or any([ np.all(board[:, i] == player) for i in range(3) ]) or np.all(np.diag(board) == player) or np.all(np.diag(np.fliplr(board)) == player) def is_draw(self, board): return "" not in board and not self.is_winner(board, self.human) and not self.is_winner(board, self.ai) def available_moves(self, board): return [(r, c) for r in range(3) for c in range(3) if board[r, c] == ""] def minimax(self, board, depth, is_maximizing): if self.is_winner(board, self.ai): return 10 - depth if self.is_winner(board, self.human): return depth - 10 if self.is_draw(board): return 0 if is_maximizing: best_score = -np.inf for (r, c) in self.available_moves(board): board[r, c] = self.ai score = self.minimax(board, depth + 1, False) board[r, c] = "" best_score = max(best_score, score) return best_score else: best_score = np.inf for (r, c) in self.available_moves(board): board[r, c] = self.human score = self.minimax(board, depth + 1, True) board[r, c] = "" best_score = min(best_score, score) return best_score def best_move(self): best_score = -np.inf move = None for (r, c) in self.available_moves(self.board): self.board[r, c] = self.ai score = self.minimax(self.board, 0, False) self.board[r, c] = "" if score > best_score: best_score = score move = (r, c) return move game = TicTacToeAI() status = "Your Turn (X)" def play(row, col): global status, game if game.board[row, col] != "": return game.board.tolist(), status, "Invalid move." game.board[row, col] = game.human if game.is_winner(game.board, game.human): status = "You Win! 🎉" return game.board.tolist(), status, "Try again?" elif game.is_draw(game.board): status = "Draw! 🤝" return game.board.tolist(), status, "Try again?" ai_r, ai_c = game.best_move() if ai_r is not None: game.board[ai_r, ai_c] = game.ai if game.is_winner(game.board, game.ai): status = "AI Wins! 🤖" return game.board.tolist(), status, "Try again?" elif game.is_draw(game.board): status = "Draw! 🤝" return game.board.tolist(), status, "Try again?" status = "Your Turn (X)" return game.board.tolist(), status, "" def reset(): global game, status game = TicTacToeAI() status = "Your Turn (X)" return game.board.tolist(), status, "" with gr.Blocks() as demo: gr.Markdown("## 🎮 Smart Tic-Tac-Toe vs AI") gr.Markdown("Click a cell to make your move. You are X, AI is O.") board = gr.Dataframe(value=game.board.tolist(), row_count=3, col_count=3, interactive=False) status_text = gr.Textbox(value=status, interactive=False, label="Game Status") tips = gr.Textbox(label="Tip", interactive=False) with gr.Row(): for r in range(3): for c in range(3): gr.Button(f"{r},{c}").click( play, inputs=[gr.Number(value=r), gr.Number(value=c)], outputs=[board, status_text, tips] ) gr.Button("Reset Game 🔄").click(reset, outputs=[board, status_text, tips]) demo.launch()