Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
import gradio as gr
|
2 |
import random
|
|
|
|
|
3 |
|
4 |
class TicTacToe:
|
5 |
def __init__(self):
|
@@ -18,136 +20,25 @@ class TicTacToe:
|
|
18 |
self.current_player = self.human
|
19 |
return self.board
|
20 |
|
21 |
-
|
22 |
-
|
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 |
-
|
35 |
-
|
36 |
-
if all(self.board[i] == player for i in combo):
|
37 |
-
return True
|
38 |
-
return False
|
39 |
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
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 |
-
#
|
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 |
|
@@ -158,7 +49,8 @@ def create_interface():
|
|
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(),
|
@@ -166,7 +58,8 @@ def create_interface():
|
|
166 |
}
|
167 |
return {status: "Invalid move!"}
|
168 |
|
169 |
-
def reset_game():
|
|
|
170 |
game.reset()
|
171 |
return {
|
172 |
status: "Your turn!",
|
@@ -176,16 +69,18 @@ def create_interface():
|
|
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()
|
|
|
1 |
import gradio as gr
|
2 |
import random
|
3 |
+
from typing import Dict
|
4 |
+
import uuid
|
5 |
|
6 |
class TicTacToe:
|
7 |
def __init__(self):
|
|
|
20 |
self.current_player = self.human
|
21 |
return self.board
|
22 |
|
23 |
+
# Rest of your TicTacToe class remains the same...
|
24 |
+
# (keeping all other methods identical)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
|
26 |
+
# Dictionary to store game instances for each session
|
27 |
+
games: Dict[str, TicTacToe] = {}
|
|
|
|
|
|
|
28 |
|
29 |
+
def get_game(session_id: str) -> TicTacToe:
|
30 |
+
if session_id not in games:
|
31 |
+
games[session_id] = TicTacToe()
|
32 |
+
return games[session_id]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
|
34 |
css = """
|
35 |
+
# Your existing CSS remains the same
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
"""
|
37 |
|
38 |
def create_interface():
|
39 |
with gr.Blocks(css=css) as demo:
|
40 |
+
session_id = gr.State(lambda: str(uuid.uuid4()))
|
41 |
+
|
42 |
with gr.Column(elem_id="game-container"):
|
43 |
status = gr.Markdown("Your turn!", elem_id="message")
|
44 |
|
|
|
49 |
|
50 |
reset = gr.Button("New Game", elem_id="reset-btn")
|
51 |
|
52 |
+
def handle_click(idx, session):
|
53 |
+
game = get_game(session)
|
54 |
if game.make_move(idx):
|
55 |
return {
|
56 |
status: game.get_status(),
|
|
|
58 |
}
|
59 |
return {status: "Invalid move!"}
|
60 |
|
61 |
+
def reset_game(session):
|
62 |
+
game = get_game(session)
|
63 |
game.reset()
|
64 |
return {
|
65 |
status: "Your turn!",
|
|
|
69 |
for i, cell in enumerate(cells):
|
70 |
cell.click(
|
71 |
handle_click,
|
72 |
+
inputs=[gr.State(i), session_id],
|
73 |
outputs=[status, *cells]
|
74 |
)
|
75 |
|
76 |
reset.click(
|
77 |
reset_game,
|
78 |
+
inputs=[session_id],
|
79 |
outputs=[status, *cells]
|
80 |
)
|
81 |
|
82 |
return demo
|
83 |
|
84 |
demo = create_interface()
|
85 |
+
demo.queue() # Enable queuing for multiple users
|
86 |
demo.launch()
|