OrifjonKenjayev commited on
Commit
87e0685
·
verified ·
1 Parent(s): c81092d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +133 -142
app.py CHANGED
@@ -1,200 +1,191 @@
1
  import gradio as gr
2
- import numpy as np
3
-
4
- # Game constants
5
- X = "X"
6
- O = "O"
7
- EMPTY = None
8
 
9
  class TicTacToe:
10
  def __init__(self):
11
- self.board = [[EMPTY for _ in range(3)] for _ in range(3)]
12
- self.current_player = X
13
- self.game_over = False
14
-
 
 
 
 
 
 
15
  def reset(self):
16
- self.board = [[EMPTY for _ in range(3)] for _ in range(3)]
17
- self.current_player = X
18
- self.game_over = False
19
-
20
- def make_move(self, row, col):
21
- if self.board[row][col] is not None or self.game_over:
22
- return False
23
-
24
- self.board[row][col] = self.current_player
25
- if self.check_winner():
26
- self.game_over = True
 
 
 
27
  return True
28
-
29
- if self.is_board_full():
30
- self.game_over = True
31
- return True
32
-
33
- self.current_player = O if self.current_player == X else X
34
- return True
35
-
36
- def check_winner(self):
37
- # Check rows
38
- for row in self.board:
39
- if row.count(row[0]) == 3 and row[0] is not None:
40
- return True
41
-
42
- # Check columns
43
- for col in range(3):
44
- if (self.board[0][col] == self.board[1][col] == self.board[2][col]
45
- and self.board[0][col] is not None):
46
  return True
47
-
48
- # Check diagonals
49
- if (self.board[0][0] == self.board[1][1] == self.board[2][2]
50
- and self.board[0][0] is not None):
51
- return True
52
- if (self.board[0][2] == self.board[1][1] == self.board[2][0]
53
- and self.board[0][2] is not None):
54
- return True
55
-
56
  return False
57
-
58
- def is_board_full(self):
59
- return all(all(cell is not None for cell in row) for row in self.board)
60
 
61
- # Initialize game
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  game = TicTacToe()
63
 
64
- # Custom CSS
65
- custom_css = """
66
  #game-container {
67
  max-width: 300px;
68
  margin: 0 auto;
69
- padding: 20px;
70
- background: #f5f5f5;
71
- border-radius: 10px;
72
  }
73
 
74
- .board-row {
75
- display: flex !important;
76
- justify-content: center !important;
77
- gap: 3px !important;
78
- margin: 3px 0 !important;
 
 
 
79
  }
80
 
81
  .cell {
82
- width: 60px !important;
83
- height: 60px !important;
84
  font-size: 24px !important;
85
  font-weight: bold !important;
86
  background: white !important;
87
- border: none !important;
88
  color: #0066cc !important;
 
89
  display: flex !important;
90
  align-items: center !important;
91
  justify-content: center !important;
92
  cursor: pointer !important;
93
- padding: 0 !important;
94
- margin: 0 !important;
95
  }
96
 
97
- .board-container {
98
- background: #ff0000;
99
- padding: 3px;
100
- width: fit-content;
101
- margin: 20px auto;
102
- border-radius: 4px;
103
  }
104
 
105
- #status-message {
106
  text-align: center;
107
  margin: 15px 0;
108
  font-size: 18px;
109
  color: #333;
110
  }
111
 
112
- #reset-button {
113
- display: block !important;
114
- margin: 20px auto !important;
115
- padding: 10px 20px !important;
116
  background: #e74c3c !important;
117
  color: white !important;
118
  border: none !important;
 
119
  border-radius: 5px !important;
120
  cursor: pointer !important;
121
- font-size: 16px !important;
122
- }
123
-
124
- #reset-button:hover {
125
- background: #c0392b !important;
126
  }
127
  """
128
 
129
- def create_board():
130
- with gr.Blocks(css=custom_css) as demo:
131
  with gr.Column(elem_id="game-container"):
132
- status = gr.Markdown("Player X's turn", elem_id="status-message")
133
-
134
- # Create board container with red background
135
- with gr.Column(elem_classes=["board-container"]):
136
- # Create 3x3 grid
137
- buttons = [[None for _ in range(3)] for _ in range(3)]
138
- for i in range(3):
139
- with gr.Row(elem_classes=["board-row"]):
140
- for j in range(3):
141
- buttons[i][j] = gr.Button(
142
- " ",
143
- elem_classes=["cell"],
144
- elem_id=f"cell-{i}-{j}"
145
- )
146
 
147
- reset_btn = gr.Button("New Game", elem_id="reset-button")
148
-
149
- def handle_click(i, j):
150
- if game.make_move(i, j):
151
- symbol = game.board[i][j]
152
- message = ""
153
-
154
- if game.game_over:
155
- if game.check_winner():
156
- message = f"Player {symbol} wins! 🎉"
157
- else:
158
- message = "It's a tie! 🤝"
159
- else:
160
- next_player = "O" if symbol == "X" else "X"
161
- message = f"Player {next_player}'s turn"
162
-
163
- # Update all buttons
164
- button_updates = {}
165
- for r in range(3):
166
- for c in range(3):
167
- value = game.board[r][c] if game.board[r][c] is not None else " "
168
- button_updates[buttons[r][c]] = value
169
-
170
- return {status: message, **button_updates}
171
 
 
 
 
 
 
 
 
 
172
  return {status: "Invalid move!"}
173
 
174
  def reset_game():
175
  game.reset()
176
- updates = {status: "Player X's turn"}
177
- for i in range(3):
178
- for j in range(3):
179
- updates[buttons[i][j]] = " "
180
- return updates
181
-
182
- # Connect event handlers
183
- for i in range(3):
184
- for j in range(3):
185
- buttons[i][j].click(
186
- lambda x, y: handle_click(x, y),
187
- inputs=[gr.State(i), gr.State(j)],
188
- outputs=[status, *sum(buttons, [])]
189
- )
190
-
191
- reset_btn.click(
192
  reset_game,
193
- outputs=[status, *sum(buttons, [])]
194
  )
195
 
196
  return demo
197
 
198
- # Launch the app
199
- demo = create_board()
200
  demo.launch()
 
1
  import gradio as gr
2
+ import random
 
 
 
 
 
3
 
4
  class TicTacToe:
5
  def __init__(self):
6
+ self.board = [" " for _ in range(9)]
7
+ self.winning_combinations = [
8
+ [0, 1, 2], [3, 4, 5], [6, 7, 8], # Rows
9
+ [0, 3, 6], [1, 4, 7], [2, 5, 8], # Columns
10
+ [0, 4, 8], [2, 4, 6] # Diagonals
11
+ ]
12
+ self.human = "X"
13
+ self.ai = "O"
14
+ self.current_player = self.human
15
+
16
  def reset(self):
17
+ self.board = [" " for _ in range(9)]
18
+ self.current_player = self.human
19
+ return self.board
20
+
21
+ def make_move(self, position):
22
+ if self.board[position] == " " and not self.is_game_over():
23
+ self.board[position] = self.current_player
24
+ if self.current_player == self.human:
25
+ self.current_player = self.ai
26
+ # AI makes its move after human
27
+ if not self.is_game_over():
28
+ ai_move = self.get_best_move()
29
+ self.board[ai_move] = self.ai
30
+ self.current_player = self.human
31
  return True
32
+ return False
33
+
34
+ def is_winner(self, player):
35
+ for combo in self.winning_combinations:
36
+ if all(self.board[i] == player for i in combo):
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  return True
 
 
 
 
 
 
 
 
 
38
  return False
 
 
 
39
 
40
+ def is_game_over(self):
41
+ return self.is_winner(self.human) or self.is_winner(self.ai) or " " not in self.board
42
+
43
+ def get_status(self):
44
+ if self.is_winner(self.human):
45
+ return "You win! 🎉"
46
+ elif self.is_winner(self.ai):
47
+ return "AI wins! 🤖"
48
+ elif " " not in self.board:
49
+ return "It's a tie! 🤝"
50
+ return "Your turn!"
51
+
52
+ def minimax(self, depth, is_maximizing):
53
+ if self.is_winner(self.ai):
54
+ return 1
55
+ if self.is_winner(self.human):
56
+ return -1
57
+ if " " not in self.board:
58
+ return 0
59
+
60
+ if is_maximizing:
61
+ best_score = float('-inf')
62
+ for i in range(9):
63
+ if self.board[i] == " ":
64
+ self.board[i] = self.ai
65
+ score = self.minimax(depth + 1, False)
66
+ self.board[i] = " "
67
+ best_score = max(score, best_score)
68
+ return best_score
69
+ else:
70
+ best_score = float('inf')
71
+ for i in range(9):
72
+ if self.board[i] == " ":
73
+ self.board[i] = self.human
74
+ score = self.minimax(depth + 1, True)
75
+ self.board[i] = " "
76
+ best_score = min(score, best_score)
77
+ return best_score
78
+
79
+ def get_best_move(self):
80
+ best_score = float('-inf')
81
+ best_move = None
82
+ for i in range(9):
83
+ if self.board[i] == " ":
84
+ self.board[i] = self.ai
85
+ score = self.minimax(0, False)
86
+ self.board[i] = " "
87
+ if score > best_score:
88
+ best_score = score
89
+ best_move = i
90
+ return best_move
91
+
92
  game = TicTacToe()
93
 
94
+ css = """
 
95
  #game-container {
96
  max-width: 300px;
97
  margin: 0 auto;
98
+ padding: 15px;
 
 
99
  }
100
 
101
+ .board {
102
+ display: grid;
103
+ grid-template-columns: repeat(3, 1fr);
104
+ gap: 4px;
105
+ background: #ff0000;
106
+ padding: 4px;
107
+ width: 240px;
108
+ margin: 0 auto;
109
  }
110
 
111
  .cell {
112
+ width: 100% !important;
113
+ height: 75px !important;
114
  font-size: 24px !important;
115
  font-weight: bold !important;
116
  background: white !important;
 
117
  color: #0066cc !important;
118
+ border: none !important;
119
  display: flex !important;
120
  align-items: center !important;
121
  justify-content: center !important;
122
  cursor: pointer !important;
 
 
123
  }
124
 
125
+ .cell:hover {
126
+ background: #f0f0f0 !important;
 
 
 
 
127
  }
128
 
129
+ #message {
130
  text-align: center;
131
  margin: 15px 0;
132
  font-size: 18px;
133
  color: #333;
134
  }
135
 
136
+ #reset-btn {
 
 
 
137
  background: #e74c3c !important;
138
  color: white !important;
139
  border: none !important;
140
+ padding: 10px 20px !important;
141
  border-radius: 5px !important;
142
  cursor: pointer !important;
143
+ margin: 10px auto !important;
144
+ display: block !important;
145
+ width: 120px !important;
 
 
146
  }
147
  """
148
 
149
+ def create_interface():
150
+ with gr.Blocks(css=css) as demo:
151
  with gr.Column(elem_id="game-container"):
152
+ status = gr.Markdown("Your turn!", elem_id="message")
 
 
 
 
 
 
 
 
 
 
 
 
 
153
 
154
+ with gr.Column(elem_classes=["board"]):
155
+ cells = []
156
+ for i in range(9):
157
+ cells.append(gr.Button(" ", elem_classes=["cell"]))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
 
159
+ reset = gr.Button("New Game", elem_id="reset-btn")
160
+
161
+ def handle_click(idx):
162
+ if game.make_move(idx):
163
+ return {
164
+ status: game.get_status(),
165
+ **{cell: game.board[i] for i, cell in enumerate(cells)}
166
+ }
167
  return {status: "Invalid move!"}
168
 
169
  def reset_game():
170
  game.reset()
171
+ return {
172
+ status: "Your turn!",
173
+ **{cell: " " for cell in cells}
174
+ }
175
+
176
+ for i, cell in enumerate(cells):
177
+ cell.click(
178
+ handle_click,
179
+ inputs=[gr.State(i)],
180
+ outputs=[status, *cells]
181
+ )
182
+
183
+ reset.click(
 
 
 
184
  reset_game,
185
+ outputs=[status, *cells]
186
  )
187
 
188
  return demo
189
 
190
+ demo = create_interface()
 
191
  demo.launch()