tictactoe / app.py
akhaliq's picture
akhaliq HF Staff
Update app.py
4ccd7dc verified
import gradio as gr
def check_winner(board):
# Check rows, columns, and diagonals for a win
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]
# Check for tie
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] # Deep copy of the board
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))
# Update the board
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:
# Switch player
current_player = 'O' if current_player == 'X' else 'X'
status = f"Player {current_player}'s turn."
game_over = False
# Update buttons based on the new board state
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 = [['', '', ''], ['', '', ''], ['', '', '']] # Corrected the board initialization
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 = []
# Arrange buttons in a 3x3 grid
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)
# Set up click events for each button
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.")