TicTacToe / app.py
OrifjonKenjayev's picture
Update app.py
2027e1d verified
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()