OrifjonKenjayev commited on
Commit
b076c5a
·
verified ·
1 Parent(s): 4783844

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +203 -86
app.py CHANGED
@@ -1,111 +1,228 @@
 
1
  import gradio as gr
2
  import numpy as np
3
  from tictactoe import X, O, EMPTY, initial_state, result, terminal, winner, minimax
4
 
5
- def initialize_board():
6
- """Initialize an empty Tic Tac Toe board."""
7
- return initial_state()
 
 
 
 
 
 
 
8
 
9
  def format_cell(cell):
10
- """Format cell for display."""
11
  return cell if cell in [X, O] else " "
12
 
13
- def make_move(board_state, row, col):
14
- """Handle player and AI moves."""
15
- if not isinstance(board_state, list):
16
- board_state = initialize_board()
17
-
18
- # Convert string representation back to EMPTY for cells
19
- board = [[cell if cell in [X, O] else EMPTY for cell in row] for row in board_state]
20
-
21
- # Player's move
22
  if board[row][col] != EMPTY:
23
- return board_state, "Invalid move! Cell already taken."
24
-
25
- # Update board with player's move
26
- board = result(board, (row, col))
27
-
28
- # Check for game over after player's move
29
- if terminal(board):
30
- game_winner = winner(board)
31
  if game_winner:
32
- return board, f"Game Over! {game_winner} wins!"
33
- return board, "Game Over! It's a tie!"
34
-
35
- # AI's move using minimax
36
- ai_move = minimax(board)
37
  if ai_move:
38
- board = result(board, ai_move)
39
-
40
- # Check for game over after AI's move
41
- if terminal(board):
42
- game_winner = winner(board)
43
- if game_winner:
44
- return board, f"Game Over! {game_winner} wins!"
45
- return board, "Game Over! It's a tie!"
46
-
47
- return board, "Your turn!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
  def create_interface():
50
- """Create the Gradio interface for Tic Tac Toe."""
51
- with gr.Blocks() as demo:
52
- gr.Markdown("# Tic Tac Toe vs AI")
53
- gr.Markdown("### You play as X, AI plays as O")
54
-
55
- # Create the game state
56
- board_state = gr.State(initialize_board())
57
-
58
- # Create the game board display
59
- with gr.Row():
60
- buttons = [[gr.Button(" ", size="lg") for _ in range(3)] for _ in range(3)]
61
-
62
- # Status message
63
- message = gr.Textbox(label="Game Status", value="Your turn!", interactive=False)
64
-
65
- # Restart button
66
- restart = gr.Button("Restart Game")
67
-
68
- # Function to update button texts
69
- def update_button_text(board):
70
- return [[format_cell(cell) for cell in row] for row in board]
71
-
72
- # Handle cell clicks
73
- def handle_click(i, j, board):
74
- new_board, msg = make_move(board, i, j)
75
- button_values = update_button_text(new_board)
76
- updates = []
77
- for row in button_values:
78
- updates.extend(row)
79
- updates.append(msg)
80
- updates.append(new_board)
81
- return updates
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
 
83
- # Connect button clicks
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  for i in range(3):
85
  for j in range(3):
86
  buttons[i][j].click(
87
- handle_click,
88
- inputs=[gr.State(i), gr.State(j), board_state],
89
- outputs=[btn for row in buttons for btn in row] + [message, board_state],
90
  )
91
-
92
- # Handle restart
93
- def handle_restart():
94
- new_board = initialize_board()
95
- button_values = update_button_text(new_board)
96
- updates = []
97
- for row in button_values:
98
- updates.extend(row)
99
- updates.append("Your turn!")
100
- updates.append(new_board)
101
- return updates
102
-
103
  restart.click(
104
  handle_restart,
105
- outputs=[btn for row in buttons for btn in row] + [message, board_state],
106
  )
107
 
108
  return demo
109
 
 
110
  demo = create_interface()
111
- demo.launch()
 
1
+ # app.py
2
  import gradio as gr
3
  import numpy as np
4
  from tictactoe import X, O, EMPTY, initial_state, result, terminal, winner, minimax
5
 
6
+ class GameState:
7
+ def __init__(self):
8
+ self.board = initial_state()
9
+ self.player_symbol = None
10
+
11
+ def reset(self):
12
+ self.board = initial_state()
13
+ self.player_symbol = None
14
+
15
+ game_state = GameState()
16
 
17
  def format_cell(cell):
 
18
  return cell if cell in [X, O] else " "
19
 
20
+ def make_move(board, row, col, player_symbol):
 
 
 
 
 
 
 
 
21
  if board[row][col] != EMPTY:
22
+ return board, "Invalid move! Cell already taken."
23
+
24
+ # Make player's move
25
+ new_board = result(board, (row, col))
26
+
27
+ if terminal(new_board):
28
+ game_winner = winner(new_board)
 
29
  if game_winner:
30
+ return new_board, f"Game Over! {game_winner} wins! 🎉"
31
+ return new_board, "Game Over! It's a tie! 🤝"
32
+
33
+ # Make AI's move
34
+ ai_move = minimax(new_board)
35
  if ai_move:
36
+ new_board = result(new_board, ai_move)
37
+
38
+ if terminal(new_board):
39
+ game_winner = winner(new_board)
40
+ if game_winner:
41
+ return new_board, f"Game Over! {game_winner} wins! 🎉"
42
+ return new_board, "Game Over! It's a tie! 🤝"
43
+
44
+ return new_board, "Your turn!"
45
+
46
+ css = """
47
+ #game-container {
48
+ max-width: 400px;
49
+ margin: 0 auto;
50
+ }
51
+ #game-board {
52
+ display: grid;
53
+ grid-template-columns: repeat(3, 1fr);
54
+ gap: 10px;
55
+ margin: 20px 0;
56
+ }
57
+ .cell-button {
58
+ aspect-ratio: 1;
59
+ font-size: 2em !important;
60
+ font-weight: bold !important;
61
+ border: 2px solid #2c3e50 !important;
62
+ border-radius: 10px !important;
63
+ background-color: #ffffff !important;
64
+ transition: all 0.3s ease !important;
65
+ min-height: 80px !important;
66
+ }
67
+ .cell-button:hover {
68
+ background-color: #f0f0f0 !important;
69
+ }
70
+ #message-box {
71
+ text-align: center;
72
+ padding: 15px;
73
+ border-radius: 10px;
74
+ background-color: #f8f9fa;
75
+ margin: 20px 0;
76
+ font-size: 1.2em !important;
77
+ }
78
+ .player-button {
79
+ padding: 10px 20px !important;
80
+ font-size: 1.2em !important;
81
+ border-radius: 8px !important;
82
+ background-color: #3498db !important;
83
+ color: white !important;
84
+ border: none !important;
85
+ transition: all 0.3s ease !important;
86
+ min-width: 120px !important;
87
+ }
88
+ .player-button:hover {
89
+ background-color: #2980b9 !important;
90
+ }
91
+ .restart-button {
92
+ background-color: #e74c3c !important;
93
+ color: white !important;
94
+ padding: 10px 20px !important;
95
+ font-size: 1.2em !important;
96
+ border-radius: 8px !important;
97
+ border: none !important;
98
+ transition: all 0.3s ease !important;
99
+ width: 100% !important;
100
+ max-width: 200px !important;
101
+ margin: 0 auto !important;
102
+ }
103
+ .restart-button:hover {
104
+ background-color: #c0392b !important;
105
+ }
106
+ .title {
107
+ text-align: center;
108
+ color: #2c3e50;
109
+ font-size: 2.5em !important;
110
+ margin-bottom: 20px !important;
111
+ }
112
+ """
113
 
114
  def create_interface():
115
+ with gr.Blocks(css=css) as demo:
116
+ gr.Markdown("# Tic Tac Toe", elem_classes=["title"])
117
+
118
+ with gr.Column(elem_id="game-container"):
119
+ # Player selection
120
+ with gr.Row(visible=True) as player_select:
121
+ select_x = gr.Button("Play as X", elem_classes=["player-button"])
122
+ select_o = gr.Button("Play as O", elem_classes=["player-button"])
123
+
124
+ # Game status
125
+ message = gr.Markdown("Choose your symbol to start!", elem_id="message-box")
126
+
127
+ # Game board
128
+ with gr.Column(visible=False) as game_board:
129
+ board_display = gr.Grid(
130
+ elem_id="game-board",
131
+ rows=3,
132
+ cols=3,
133
+ value=[[" " for _ in range(3)] for _ in range(3)],
134
+ render=False
135
+ )
136
+
137
+ buttons = [[None for _ in range(3)] for _ in range(3)]
138
+ for i in range(3):
139
+ for j in range(3):
140
+ buttons[i][j] = gr.Button(
141
+ " ",
142
+ elem_classes=["cell-button"],
143
+ elem_id=f"cell-{i}-{j}"
144
+ )
145
+
146
+ restart = gr.Button("New Game", elem_classes=["restart-button"])
147
+
148
+ def start_game(symbol):
149
+ game_state.reset()
150
+ game_state.player_symbol = symbol
151
+ game_state.board = initial_state()
152
+
153
+ msg = "Your turn!"
154
+ if symbol == O:
155
+ # If player chose O, AI (X) makes the first move
156
+ ai_move = minimax(game_state.board)
157
+ game_state.board = result(game_state.board, ai_move)
158
+
159
+ return {
160
+ player_select: gr.update(visible=False),
161
+ game_board: gr.update(visible=True),
162
+ message: msg,
163
+ **{buttons[i][j]: format_cell(game_state.board[i][j])
164
+ for i in range(3) for j in range(3)}
165
+ }
166
+
167
+ def handle_click(i, j):
168
+ if game_state.board[i][j] != EMPTY:
169
+ return {
170
+ message: "Invalid move! Cell already taken.",
171
+ **{buttons[r][c]: format_cell(game_state.board[r][c])
172
+ for r in range(3) for c in range(3)}
173
+ }
174
+
175
+ new_board, msg = make_move(
176
+ game_state.board,
177
+ i,
178
+ j,
179
+ game_state.player_symbol
180
+ )
181
+ game_state.board = new_board
182
+
183
+ return {
184
+ message: msg,
185
+ **{buttons[r][c]: format_cell(new_board[r][c])
186
+ for r in range(3) for c in range(3)}
187
+ }
188
 
189
+ def handle_restart():
190
+ game_state.reset()
191
+ return {
192
+ player_select: gr.update(visible=True),
193
+ game_board: gr.update(visible=False),
194
+ message: "Choose your symbol to start!",
195
+ **{buttons[i][j]: " " for i in range(3) for j in range(3)}
196
+ }
197
+
198
+ # Connect event handlers
199
+ select_x.click(
200
+ start_game,
201
+ inputs=[gr.State(X)],
202
+ outputs=[player_select, game_board, message, *sum(buttons, [])]
203
+ )
204
+
205
+ select_o.click(
206
+ start_game,
207
+ inputs=[gr.State(O)],
208
+ outputs=[player_select, game_board, message, *sum(buttons, [])]
209
+ )
210
+
211
  for i in range(3):
212
  for j in range(3):
213
  buttons[i][j].click(
214
+ lambda x, y: handle_click(x, y),
215
+ inputs=[gr.State(i), gr.State(j)],
216
+ outputs=[message, *sum(buttons, [])]
217
  )
218
+
 
 
 
 
 
 
 
 
 
 
 
219
  restart.click(
220
  handle_restart,
221
+ outputs=[player_select, game_board, message, *sum(buttons, [])]
222
  )
223
 
224
  return demo
225
 
226
+
227
  demo = create_interface()
228
+ demo.launch()