Spaces:
Sleeping
Sleeping
import gradio as gr | |
import numpy as np | |
import matplotlib.pyplot as plt | |
import random | |
class Minesweeper: | |
def __init__(self, width=8, height=8, num_mines=10): | |
self.width = width | |
self.height = height | |
self.num_mines = num_mines | |
self.game_over = False | |
self.won = False | |
self.first_move = True | |
self.initialize_board() | |
def initialize_board(self): | |
self.board = np.zeros((self.height, self.width), dtype=int) | |
self.visible_board = np.full((self.height, self.width), -2, dtype=int) | |
def place_mines(self, first_x, first_y): | |
positions = [(x, y) for x in range(self.height) for y in range(self.width)] | |
positions.remove((first_x, first_y)) | |
mine_positions = random.sample(positions, self.num_mines) | |
for x, y in mine_positions: | |
self.board[x, y] = -1 | |
for x in range(self.height): | |
for y in range(self.width): | |
if self.board[x, y] != -1: | |
self.board[x, y] = self.count_adjacent_mines(x, y) | |
def count_adjacent_mines(self, x, y): | |
count = 0 | |
for dx in [-1, 0, 1]: | |
for dy in [-1, 0, 1]: | |
if dx == 0 and dy == 0: | |
continue | |
new_x, new_y = x + dx, y + dy | |
if (0 <= new_x < self.height and | |
0 <= new_y < self.width and | |
self.board[new_x, new_y] == -1): | |
count += 1 | |
return count | |
def reveal(self, x, y): | |
if self.game_over or self.won: | |
return | |
if self.first_move: | |
self.place_mines(x, y) | |
self.first_move = False | |
if self.board[x, y] == -1: | |
self.game_over = True | |
return | |
self.flood_fill(x, y) | |
if np.count_nonzero(self.visible_board == -2) == self.num_mines: | |
self.won = True | |
def flood_fill(self, x, y): | |
if (not (0 <= x < self.height and 0 <= y < self.width) or | |
self.visible_board[x, y] != -2): | |
return | |
self.visible_board[x, y] = self.board[x, y] | |
if self.board[x, y] == 0: | |
for dx in [-1, 0, 1]: | |
for dy in [-1, 0, 1]: | |
self.flood_fill(x + dx, y + dy) | |
def toggle_flag(self, x, y): | |
if self.game_over or self.won: | |
return | |
if self.visible_board[x, y] == -2: | |
self.visible_board[x, y] = -1 | |
elif self.visible_board[x, y] == -1: | |
self.visible_board[x, y] = -2 | |
def create_board_image(game): | |
fig, ax = plt.subplots(figsize=(8, 8)) | |
colors = { | |
-2: '#CCCCCC', # Coberto | |
-1: '#FF0000', # Bandeira/Mina | |
0: '#FFFFFF', # Vazio | |
1: '#0000FF', # Azul | |
2: '#008000', # Verde | |
3: '#FF0000', # Vermelho | |
4: '#000080', # Azul escuro | |
5: '#800000', # Vermelho escuro | |
6: '#008080', # Ciano | |
7: '#000000', # Preto | |
8: '#808080' # Cinza | |
} | |
for i in range(game.height): | |
for j in range(game.width): | |
color = colors[game.visible_board[i, j]] | |
ax.add_patch(plt.Rectangle((j, game.height-1-i), 1, 1, facecolor=color, edgecolor='black')) | |
if game.visible_board[i, j] > 0: | |
plt.text(j+0.5, game.height-1-i+0.5, str(game.visible_board[i, j]), | |
horizontalalignment='center', | |
verticalalignment='center', | |
color='black') | |
elif game.visible_board[i, j] == -1: | |
plt.text(j+0.5, game.height-1-i+0.5, 'F', | |
horizontalalignment='center', | |
verticalalignment='center', | |
color='black') | |
if game.game_over: | |
for i in range(game.height): | |
for j in range(game.width): | |
if game.board[i, j] == -1: | |
ax.add_patch(plt.Rectangle((j, game.height-1-i), 1, 1, facecolor='red', edgecolor='black')) | |
plt.text(j+0.5, game.height-1-i+0.5, 'M', | |
horizontalalignment='center', | |
verticalalignment='center', | |
color='black') | |
ax.set_xlim(0, game.width) | |
ax.set_ylim(0, game.height) | |
ax.set_xticks(range(game.width)) | |
ax.set_yticks(range(game.height)) | |
ax.grid(True) | |
status = "Jogando" | |
if game.game_over: | |
status = "Game Over!" | |
elif game.won: | |
status = "Você Venceu!" | |
plt.title(f'Campo Minado - {status}') | |
return fig | |
def make_move(x, y, action, game_state): | |
if not game_state: | |
game = Minesweeper(8, 8, 10) | |
else: | |
game = Minesweeper(8, 8, 10) | |
game.__dict__ = game_state | |
if action == "reveal": | |
game.reveal(x, y) | |
else: | |
game.toggle_flag(x, y) | |
fig = create_board_image(game) | |
status = "Jogando" | |
if game.game_over: | |
status = "Game Over!" | |
elif game.won: | |
status = "Você Venceu!" | |
return fig, game.__dict__, status | |
def new_game(): | |
game = Minesweeper(8, 8, 10) | |
fig = create_board_image(game) | |
return fig, game.__dict__, "Novo jogo iniciado!" | |
with gr.Blocks(title="Campo Minado") as demo: | |
gr.Markdown(""" | |
# Campo Minado | |
Instruções: | |
1. Digite as coordenadas (0-7) para linha e coluna | |
2. Escolha "Revelar" para abrir uma célula ou "Bandeira" para marcar uma mina | |
3. Evite as minas e revele todas as células seguras! | |
""") | |
game_state = gr.State() | |
board = gr.Plot(label="Tabuleiro") | |
status = gr.Textbox(label="Status do Jogo", interactive=False) | |
with gr.Row(): | |
x_coord = gr.Number(label="Linha (0-7)", minimum=0, maximum=7, step=1) | |
y_coord = gr.Number(label="Coluna (0-7)", minimum=0, maximum=7, step=1) | |
with gr.Row(): | |
reveal_btn = gr.Button("Revelar") | |
flag_btn = gr.Button("Bandeira") | |
new_game_btn = gr.Button("Novo Jogo") | |
reveal_btn.click( | |
make_move, | |
inputs=[x_coord, y_coord, gr.Textbox(value="reveal", visible=False), game_state], | |
outputs=[board, game_state, status] | |
) | |
flag_btn.click( | |
make_move, | |
inputs=[x_coord, y_coord, gr.Textbox(value="flag", visible=False), game_state], | |
outputs=[board, game_state, status] | |
) | |
new_game_btn.click(new_game, outputs=[board, game_state, status]) | |
demo.load(new_game, outputs=[board, game_state, status]) | |
demo.launch() |