Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import random | |
| class TicTacToe: | |
| def __init__(self): | |
| self.board = [' ' for _ in range(9)] | |
| self.current_player = 'X' | |
| self.game_over = False | |
| self.winner = None | |
| self.player_wins = 0 | |
| self.ai_wins = 0 | |
| self.ties = 0 | |
| def reset_game(self): | |
| self.board = [' ' for _ in range(9)] | |
| self.current_player = 'X' | |
| self.game_over = False | |
| self.winner = None | |
| def make_move(self, position): | |
| if self.board[position] == ' ' and not self.game_over: | |
| self.board[position] = self.current_player | |
| if self.check_winner(): | |
| self.game_over = True | |
| self.winner = self.current_player | |
| if self.current_player == 'X': | |
| self.player_wins += 1 | |
| else: | |
| self.ai_wins += 1 | |
| elif ' ' not in self.board: | |
| self.game_over = True | |
| self.winner = 'Tie' | |
| self.ties += 1 | |
| else: | |
| self.current_player = 'O' if self.current_player == 'X' else 'X' | |
| return True | |
| return False | |
| def check_winner(self): | |
| lines = [ | |
| [0, 1, 2], [3, 4, 5], [6, 7, 8], | |
| [0, 3, 6], [1, 4, 7], [2, 5, 8], | |
| [0, 4, 8], [2, 4, 6] | |
| ] | |
| for line in lines: | |
| if self.board[line[0]] == self.board[line[1]] == self.board[line[2]] != ' ': | |
| return True | |
| return False | |
| def ai_move(self): | |
| move = self.find_best_move() | |
| if move is not None: | |
| self.make_move(move) | |
| def find_best_move(self): | |
| for i in range(9): | |
| if self.board[i] == ' ': | |
| self.board[i] = 'O' | |
| if self.check_winner(): | |
| self.board[i] = ' ' | |
| return i | |
| self.board[i] = ' ' | |
| for i in range(9): | |
| if self.board[i] == ' ': | |
| self.board[i] = 'X' | |
| if self.check_winner(): | |
| self.board[i] = ' ' | |
| return i | |
| self.board[i] = ' ' | |
| if self.board[4] == ' ': | |
| return 4 | |
| corners = [0, 2, 6, 8] | |
| available = [i for i in corners if self.board[i] == ' '] | |
| if available: | |
| return random.choice(available) | |
| empty = [i for i in range(9) if self.board[i] == ' '] | |
| return random.choice(empty) if empty else None | |
| game = TicTacToe() | |
| def make_player_move(position): | |
| if game.game_over: | |
| return update_display() + ("Game Over! Click 'New Game' to play again.",) | |
| if game.make_move(position): | |
| if game.game_over: | |
| return update_display() + (get_game_status(),) | |
| game.ai_move() | |
| return update_display() + (get_game_status(),) | |
| return update_display() + ("Invalid move! Try another cell.",) | |
| def new_game(): | |
| game.reset_game() | |
| return update_display() + ("New game started! You are β, make your move!",) | |
| def update_display(): | |
| return tuple( | |
| gr.update(value="β" if c == 'X' else "β" if c == 'O' else "", | |
| variant="primary" if c == 'X' else "stop" if c == 'O' else "secondary", | |
| interactive=(c == ' ' and not game.game_over)) | |
| for c in game.board | |
| ) | |
| def get_game_status(): | |
| if game.game_over: | |
| if game.winner == 'X': | |
| return "π You Win! Congratulations!" | |
| elif game.winner == 'O': | |
| return "π€ AI Wins! Try again!" | |
| return "π€ It's a Tie!" | |
| return "Your turn!" if game.current_player == 'X' else "AI is thinking... π€" | |
| with gr.Blocks( | |
| theme=gr.themes.Soft(), | |
| title="π― Smart Tic-Tac-Toe vs AI", | |
| css=""" | |
| .game-button { | |
| height: 80px; | |
| font-size: 2em; | |
| } | |
| """ | |
| ) as demo: | |
| gr.Markdown("# π― Smart Tic-Tac-Toe vs AI") | |
| gr.Markdown("### You are β, AI is β β Get 3 in a row to win!") | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| with gr.Row(): | |
| btn0 = gr.Button("", elem_classes="game-button") | |
| btn1 = gr.Button("", elem_classes="game-button") | |
| btn2 = gr.Button("", elem_classes="game-button") | |
| with gr.Row(): | |
| btn3 = gr.Button("", elem_classes="game-button") | |
| btn4 = gr.Button("", elem_classes="game-button") | |
| btn5 = gr.Button("", elem_classes="game-button") | |
| with gr.Row(): | |
| btn6 = gr.Button("", elem_classes="game-button") | |
| btn7 = gr.Button("", elem_classes="game-button") | |
| btn8 = gr.Button("", elem_classes="game-button") | |
| new_game_btn = gr.Button("π New Game", variant="primary") | |
| status_display = gr.Textbox( | |
| label="Game Status", | |
| value="New game started! You are β, make your move!", | |
| lines=2, interactive=False | |
| ) | |
| with gr.Column(scale=1): | |
| gr.Markdown("### π Game Stats") | |
| player_wins_display = gr.Number(label="π Your Wins", value=0, interactive=False) | |
| ai_wins_display = gr.Number(label="π€ AI Wins", value=0, interactive=False) | |
| ties_display = gr.Number(label="π€ Ties", value=0, interactive=False) | |
| with gr.Accordion("π‘ Strategy Tips", open=False): | |
| gr.Markdown(""" | |
| - Take the center if available | |
| - Block your opponentβs winning move | |
| - Create multiple win paths | |
| - Think ahead β the AI does! | |
| """) | |
| buttons = [btn0, btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8] | |
| for i, btn in enumerate(buttons): | |
| btn.click(fn=lambda pos=i: make_player_move(pos), outputs=buttons + [status_display]) | |
| new_game_btn.click(fn=new_game, outputs=buttons + [status_display]) | |
| def update_stats(): | |
| return game.player_wins, game.ai_wins, game.ties | |
| for btn in buttons: | |
| btn.click(fn=update_stats, outputs=[player_wins_display, ai_wins_display, ties_display]) | |
| new_game_btn.click(fn=update_stats, outputs=[player_wins_display, ai_wins_display, ties_display]) | |
| # Required for Hugging Face Spaces | |
| model = demo | |
| # β REQUIRED to launch on Hugging Face | |
| if __name__ == "__main__": | |
| demo.launch() | |