|
import gradio as gr |
|
|
|
|
|
def check_winner(board): |
|
wins = [ |
|
[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 i, j, k in wins: |
|
if board[i] == board[j] == board[k] and board[i] != "": |
|
return board[i] |
|
if "" not in board: |
|
return "Draw" |
|
return None |
|
|
|
def minimax(board, is_maximizing): |
|
winner = check_winner(board) |
|
if winner == "O": return 1 |
|
if winner == "X": return -1 |
|
if winner == "Draw": return 0 |
|
|
|
if is_maximizing: |
|
best = -float("inf") |
|
for i in range(9): |
|
if board[i] == "": |
|
board[i] = "O" |
|
score = minimax(board, False) |
|
board[i] = "" |
|
best = max(best, score) |
|
return best |
|
else: |
|
best = float("inf") |
|
for i in range(9): |
|
if board[i] == "": |
|
board[i] = "X" |
|
score = minimax(board, True) |
|
board[i] = "" |
|
best = min(best, score) |
|
return best |
|
|
|
def ai_move(board): |
|
best_score = -float("inf") |
|
move = None |
|
for i in range(9): |
|
if board[i] == "": |
|
board[i] = "O" |
|
score = minimax(board, False) |
|
board[i] = "" |
|
if score > best_score: |
|
best_score = score |
|
move = i |
|
return move |
|
|
|
def play_game(board, move): |
|
if board[move] != "": |
|
return board, "Invalid move!" |
|
board[move] = "X" |
|
winner = check_winner(board) |
|
if winner: |
|
return board, f"Winner: {winner}" |
|
|
|
ai = ai_move(board) |
|
if ai is not None: |
|
board[ai] = "O" |
|
winner = check_winner(board) |
|
if winner: |
|
return board, f"Winner: {winner}" |
|
return board, "Your turn" |
|
|
|
def reset_game(): |
|
return [""] * 9, "Game reset!" |
|
|
|
|
|
with gr.Blocks() as demo: |
|
gr.Markdown("## Smart Tic-Tac-Toe vs AI") |
|
board_state = gr.State([""] * 9) |
|
status = gr.Label(value="Your turn") |
|
buttons = [] |
|
with gr.Row(): |
|
for i in range(3): |
|
with gr.Column(): |
|
for j in range(3): |
|
idx = i*3 + j |
|
btn = gr.Button("") |
|
buttons.append(btn) |
|
|
|
reset_btn = gr.Button("Reset Game") |
|
|
|
for idx, btn in enumerate(buttons): |
|
btn.click(fn=play_game, inputs=[board_state, gr.Number(value=idx)], outputs=[board_state, status]) |
|
|
|
reset_btn.click(fn=reset_game, inputs=None, outputs=[board_state, status]) |
|
|
|
demo.launch() |
|
|