DHEIVER commited on
Commit
889df23
·
verified ·
1 Parent(s): 1aa1918

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +197 -0
app.py ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import matplotlib.pyplot as plt
4
+ import random
5
+
6
+ class Minesweeper:
7
+ def __init__(self, width=8, height=8, num_mines=10):
8
+ self.width = width
9
+ self.height = height
10
+ self.num_mines = num_mines
11
+ self.game_over = False
12
+ self.won = False
13
+ self.first_move = True
14
+ self.initialize_board()
15
+
16
+ def initialize_board(self):
17
+ # Tabuleiro com as minas (-1 para minas, 0-8 para números)
18
+ self.board = np.zeros((self.height, self.width), dtype=int)
19
+ # Tabuleiro visível para o jogador (-2 coberto, -1 bandeira, números para revelados)
20
+ self.visible_board = np.full((self.height, self.width), -2, dtype=int)
21
+
22
+ def place_mines(self, first_x, first_y):
23
+ # Coloca minas aleatoriamente, evitando a primeira posição clicada
24
+ positions = [(x, y) for x in range(self.height) for y in range(self.width)]
25
+ positions.remove((first_x, first_y))
26
+ mine_positions = random.sample(positions, self.num_mines)
27
+
28
+ for x, y in mine_positions:
29
+ self.board[x, y] = -1
30
+
31
+ # Calcula números para células adjacentes às minas
32
+ for x in range(self.height):
33
+ for y in range(self.width):
34
+ if self.board[x, y] != -1:
35
+ self.board[x, y] = self.count_adjacent_mines(x, y)
36
+
37
+ def count_adjacent_mines(self, x, y):
38
+ count = 0
39
+ for dx in [-1, 0, 1]:
40
+ for dy in [-1, 0, 1]:
41
+ if dx == 0 and dy == 0:
42
+ continue
43
+ new_x, new_y = x + dx, y + dy
44
+ if (0 <= new_x < self.height and
45
+ 0 <= new_y < self.width and
46
+ self.board[new_x, new_y] == -1):
47
+ count += 1
48
+ return count
49
+
50
+ def reveal(self, x, y):
51
+ if self.game_over or self.won:
52
+ return
53
+
54
+ if self.first_move:
55
+ self.place_mines(x, y)
56
+ self.first_move = False
57
+
58
+ # Se clicou em uma mina
59
+ if self.board[x, y] == -1:
60
+ self.game_over = True
61
+ return
62
+
63
+ # Revela a célula clicada
64
+ self.flood_fill(x, y)
65
+
66
+ # Verifica vitória
67
+ if np.count_nonzero(self.visible_board == -2) == self.num_mines:
68
+ self.won = True
69
+
70
+ def flood_fill(self, x, y):
71
+ if (not (0 <= x < self.height and 0 <= y < self.width) or
72
+ self.visible_board[x, y] != -2):
73
+ return
74
+
75
+ self.visible_board[x, y] = self.board[x, y]
76
+
77
+ if self.board[x, y] == 0:
78
+ for dx in [-1, 0, 1]:
79
+ for dy in [-1, 0, 1]:
80
+ self.flood_fill(x + dx, y + dy)
81
+
82
+ def toggle_flag(self, x, y):
83
+ if self.game_over or self.won:
84
+ return
85
+
86
+ if self.visible_board[x, y] == -2:
87
+ self.visible_board[x, y] = -1
88
+ elif self.visible_board[x, y] == -1:
89
+ self.visible_board[x, y] = -2
90
+
91
+ def create_board_image(game):
92
+ fig, ax = plt.subplots(figsize=(8, 8))
93
+
94
+ # Cores para diferentes números
95
+ colors = {
96
+ -2: '#CCCCCC', # Coberto
97
+ -1: '#FF0000', # Bandeira/Mina
98
+ 0: '#FFFFFF', # Vazio
99
+ 1: '#0000FF', # Azul
100
+ 2: '#008000', # Verde
101
+ 3: '#FF0000', # Vermelho
102
+ 4: '#000080', # Azul escuro
103
+ 5: '#800000', # Vermelho escuro
104
+ 6: '#008080', # Ciano
105
+ 7: '#000000', # Preto
106
+ 8: '#808080' # Cinza
107
+ }
108
+
109
+ # Desenha células
110
+ for i in range(game.height):
111
+ for j in range(game.width):
112
+ color = colors[game.visible_board[i, j]]
113
+ ax.add_patch(plt.Rectangle((j, game.height-1-i), 1, 1, facecolor=color, edgecolor='black'))
114
+
115
+ # Adiciona números
116
+ if game.visible_board[i, j] > 0:
117
+ plt.text(j+0.5, game.height-1-i+0.5, str(game.visible_board[i, j]),
118
+ horizontalalignment='center',
119
+ verticalalignment='center',
120
+ color='black')
121
+ elif game.visible_board[i, j] == -1:
122
+ plt.text(j+0.5, game.height-1-i+0.5, 'F',
123
+ horizontalalignment='center',
124
+ verticalalignment='center',
125
+ color='black')
126
+
127
+ # Mostra todas as minas se o jogo acabou
128
+ if game.game_over:
129
+ for i in range(game.height):
130
+ for j in range(game.width):
131
+ if game.board[i, j] == -1:
132
+ ax.add_patch(plt.Rectangle((j, game.height-1-i), 1, 1, facecolor='red', edgecolor='black'))
133
+ plt.text(j+0.5, game.height-1-i+0.5, 'M',
134
+ horizontalalignment='center',
135
+ verticalalignment='center',
136
+ color='black')
137
+
138
+ ax.set_xlim(0, game.width)
139
+ ax.set_ylim(0, game.height)
140
+ ax.set_xticks(range(game.width))
141
+ ax.set_yticks(range(game.height))
142
+ ax.grid(True)
143
+
144
+ status = "Jogando"
145
+ if game.game_over:
146
+ status = "Game Over!"
147
+ elif game.won:
148
+ status = "Você Venceu!"
149
+
150
+ plt.title(f'Campo Minado - {status}')
151
+ return fig
152
+
153
+ def handle_click(pos, button, game_state):
154
+ if not pos:
155
+ return None, game_state
156
+
157
+ x, y = int(pos[1]), int(pos[0])
158
+ game = Minesweeper(8, 8, 10)
159
+ game.__dict__ = game_state
160
+
161
+ if button == "left":
162
+ game.reveal(x, y)
163
+ else:
164
+ game.toggle_flag(x, y)
165
+
166
+ fig = create_board_image(game)
167
+ return fig, game.__dict__
168
+
169
+ def new_game():
170
+ game = Minesweeper(8, 8, 10)
171
+ fig = create_board_image(game)
172
+ return fig, game.__dict__
173
+
174
+ with gr.Blocks(title="Campo Minado") as demo:
175
+ gr.Markdown("""
176
+ # Campo Minado
177
+
178
+ Instruções:
179
+ - Clique esquerdo para revelar uma célula
180
+ - Clique direito para colocar/remover bandeira
181
+ - Evite as minas!
182
+ - Descubra todas as células sem minas para vencer
183
+ """)
184
+
185
+ game_state = gr.State()
186
+ board = gr.Plot(label="Tabuleiro")
187
+
188
+ with gr.Row():
189
+ new_game_btn = gr.Button("Novo Jogo")
190
+
191
+ board.select(handle_click, [board, gr.Button.update(value="left"), game_state], [board, game_state])
192
+ board.select(handle_click, [board, gr.Button.update(value="right"), game_state], [board, game_state], trigger_mode="right_click")
193
+ new_game_btn.click(new_game, outputs=[board, game_state])
194
+
195
+ demo.load(new_game, outputs=[board, game_state])
196
+
197
+ demo.launch()