|
import gradio as gr |
|
|
|
def check_winner(board): |
|
|
|
for i in range(3): |
|
if board[i][0] == board[i][1] == board[i][2] != '': |
|
return board[i][0] |
|
if board[0][i] == board[1][i] == board[2][i] != '': |
|
return board[0][i] |
|
if board[0][0] == board[1][1] == board[2][2] != '': |
|
return board[0][0] |
|
if board[0][2] == board[1][1] == board[2][0] != '': |
|
return board[0][2] |
|
|
|
if all(cell != '' for row in board for cell in row): |
|
return 'Tie' |
|
return None |
|
|
|
def handle_move(cell_index, board_state, current_player_state, game_over_state): |
|
try: |
|
print(f"Handle move called: cell_index={cell_index}, board_state={board_state}, current_player={current_player_state}, game_over={game_over_state}") |
|
board = [row[:] for row in board_state] |
|
current_player = current_player_state |
|
row = cell_index // 3 |
|
col = cell_index % 3 |
|
|
|
if board[row][col] != '' or game_over_state: |
|
status = f"Invalid move. Player {current_player}'s turn." |
|
return (board, status, current_player, game_over_state, *update_buttons(board, not game_over_state)) |
|
|
|
|
|
board[row][col] = current_player |
|
winner = check_winner(board) |
|
|
|
if winner: |
|
if winner == 'Tie': |
|
status = "It's a tie! Game over." |
|
else: |
|
status = f"Player {winner} wins! Game over." |
|
game_over = True |
|
else: |
|
|
|
current_player = 'O' if current_player == 'X' else 'X' |
|
status = f"Player {current_player}'s turn." |
|
game_over = False |
|
|
|
|
|
btn_updates = update_buttons(board, not game_over) |
|
print(f"Game over: {game_over}") |
|
print(f"Returning: board={board}, status={status}, current_player={current_player}") |
|
return (board, status, current_player, game_over, *btn_updates) |
|
except Exception as e: |
|
print(f"An error occurred: {str(e)}") |
|
return (board_state, "An error occurred. Please try again.", current_player_state, game_over_state, *update_buttons(board_state, not game_over_state)) |
|
|
|
def update_buttons(board, game_active): |
|
updates = [] |
|
for i in range(9): |
|
row = i // 3 |
|
col = i % 3 |
|
cell_value = board[row][col] |
|
if cell_value == '': |
|
updates.append(gr.update(value='', interactive=game_active)) |
|
else: |
|
updates.append(gr.update(value=cell_value, interactive=False)) |
|
return updates |
|
|
|
def reset_game(): |
|
board = [['', '', ''], ['', '', ''], ['', '', '']] |
|
return (board, "Player X's turn", 'X', False, *update_buttons(board, True)) |
|
|
|
with gr.Blocks(css=""" |
|
.tic-btn { |
|
width: 100px !important; |
|
height: 100px !important; |
|
font-size: 48px !important; |
|
} |
|
""") as demo: |
|
board_state = gr.State([['', '', ''], ['', '', ''], ['', '', '']]) |
|
current_player_state = gr.State('X') |
|
game_over_state = gr.State(False) |
|
status = gr.Markdown(value="Player X's turn") |
|
|
|
buttons = [] |
|
|
|
with gr.Column(): |
|
for i in range(0, 9, 3): |
|
with gr.Row(): |
|
for j in range(3): |
|
btn = gr.Button(value='', interactive=True, elem_classes='tic-btn') |
|
buttons.append(btn) |
|
|
|
|
|
for idx, btn in enumerate(buttons): |
|
btn.click( |
|
fn=handle_move, |
|
inputs=[gr.State(idx), board_state, current_player_state, game_over_state], |
|
outputs=[board_state, status, current_player_state, game_over_state] + buttons |
|
) |
|
|
|
new_game_btn = gr.Button("New Game") |
|
new_game_btn.click( |
|
fn=reset_game, |
|
inputs=[], |
|
outputs=[board_state, status, current_player_state, game_over_state] + buttons |
|
) |
|
|
|
if __name__ == "__main__": |
|
print("Starting Gradio app...") |
|
demo.launch() |
|
print("Gradio app launched.") |
|
|