Spaces:
Sleeping
Sleeping
| 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() | |