File size: 4,167 Bytes
d3eb5bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4ccd7dc
 
d3eb5bd
 
 
 
 
 
 
 
 
 
4ccd7dc
d3eb5bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4ccd7dc
 
d3eb5bd
 
 
 
 
 
 
 
 
 
 
dd10185
d3eb5bd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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.")