Spaces:
Sleeping
Sleeping
import gradio as gr | |
import random | |
class TicTacToe: | |
def __init__(self): | |
self.board = [" " for _ in range(9)] | |
self.winning_combinations = [ | |
[0, 1, 2], [3, 4, 5], [6, 7, 8], # Rows | |
[0, 3, 6], [1, 4, 7], [2, 5, 8], # Columns | |
[0, 4, 8], [2, 4, 6] # Diagonals | |
] | |
self.human = "X" | |
self.ai = "O" | |
self.current_player = self.human | |
def reset(self): | |
self.board = [" " for _ in range(9)] | |
self.current_player = self.human | |
return self.board | |
def make_move(self, position): | |
if self.board[position] == " " and not self.is_game_over(): | |
self.board[position] = self.current_player | |
if self.current_player == self.human: | |
self.current_player = self.ai | |
# AI makes its move after human | |
if not self.is_game_over(): | |
ai_move = self.get_best_move() | |
self.board[ai_move] = self.ai | |
self.current_player = self.human | |
return True | |
return False | |
def is_winner(self, player): | |
for combo in self.winning_combinations: | |
if all(self.board[i] == player for i in combo): | |
return True | |
return False | |
def is_game_over(self): | |
return self.is_winner(self.human) or self.is_winner(self.ai) or " " not in self.board | |
def get_status(self): | |
if self.is_winner(self.human): | |
return "You win! π" | |
elif self.is_winner(self.ai): | |
return "AI wins! π€" | |
elif " " not in self.board: | |
return "It's a tie! π€" | |
return "Your turn!" | |
def minimax(self, depth, is_maximizing): | |
if self.is_winner(self.ai): | |
return 1 | |
if self.is_winner(self.human): | |
return -1 | |
if " " not in self.board: | |
return 0 | |
if is_maximizing: | |
best_score = float('-inf') | |
for i in range(9): | |
if self.board[i] == " ": | |
self.board[i] = self.ai | |
score = self.minimax(depth + 1, False) | |
self.board[i] = " " | |
best_score = max(score, best_score) | |
return best_score | |
else: | |
best_score = float('inf') | |
for i in range(9): | |
if self.board[i] == " ": | |
self.board[i] = self.human | |
score = self.minimax(depth + 1, True) | |
self.board[i] = " " | |
best_score = min(score, best_score) | |
return best_score | |
def get_best_move(self): | |
best_score = float('-inf') | |
best_move = None | |
for i in range(9): | |
if self.board[i] == " ": | |
self.board[i] = self.ai | |
score = self.minimax(0, False) | |
self.board[i] = " " | |
if score > best_score: | |
best_score = score | |
best_move = i | |
return best_move | |
game = TicTacToe() | |
css = """ | |
#game-container { | |
max-width: 300px; | |
margin: 0 auto; | |
padding: 15px; | |
} | |
.board { | |
display: grid; | |
grid-template-columns: repeat(3, 1fr); | |
gap: 4px; | |
background: #ff0000; | |
padding: 4px; | |
width: 240px; | |
margin: 0 auto; | |
} | |
.cell { | |
width: 100% !important; | |
height: 75px !important; | |
font-size: 24px !important; | |
font-weight: bold !important; | |
background: white !important; | |
color: #0066cc !important; | |
border: none !important; | |
display: flex !important; | |
align-items: center !important; | |
justify-content: center !important; | |
cursor: pointer !important; | |
} | |
.cell:hover { | |
background: #f0f0f0 !important; | |
} | |
#message { | |
text-align: center; | |
margin: 15px 0; | |
font-size: 18px; | |
color: #333; | |
} | |
#reset-btn { | |
background: #e74c3c !important; | |
color: white !important; | |
border: none !important; | |
padding: 10px 20px !important; | |
border-radius: 5px !important; | |
cursor: pointer !important; | |
margin: 10px auto !important; | |
display: block !important; | |
width: 120px !important; | |
} | |
""" | |
def create_interface(): | |
with gr.Blocks(css=css) as demo: | |
with gr.Column(elem_id="game-container"): | |
status = gr.Markdown("Your turn!", elem_id="message") | |
with gr.Column(elem_classes=["board"]): | |
cells = [] | |
for i in range(9): | |
cells.append(gr.Button(" ", elem_classes=["cell"])) | |
reset = gr.Button("New Game", elem_id="reset-btn") | |
def handle_click(idx): | |
if game.make_move(idx): | |
return { | |
status: game.get_status(), | |
**{cell: game.board[i] for i, cell in enumerate(cells)} | |
} | |
return {status: "Invalid move!"} | |
def reset_game(): | |
game.reset() | |
return { | |
status: "Your turn!", | |
**{cell: " " for cell in cells} | |
} | |
for i, cell in enumerate(cells): | |
cell.click( | |
handle_click, | |
inputs=[gr.State(i)], | |
outputs=[status, *cells] | |
) | |
reset.click( | |
reset_game, | |
outputs=[status, *cells] | |
) | |
return demo | |
demo = create_interface() | |
demo.launch() |