Minesweeper / app.py
marvinisjarvis's picture
Update app.py
2308956 verified
import gradio as gr
import random
# === Game Configuration ===
BOARD_WIDTH = 10
BOARD_HEIGHT = 10
NUM_MINES = 15
# === Global Game State ===
game_state = {
"board": [],
"game_over": False,
"win": False
}
# === Board Initialization ===
def initialize_board(width, height, num_mines):
board = [[{'mine': False, 'revealed': False, 'flagged': False, 'adjacent': 0}
for _ in range(width)] for _ in range(height)]
# Random mine placement
mines = set()
while len(mines) < num_mines:
r = random.randint(0, height - 1)
c = random.randint(0, width - 1)
if not board[r][c]['mine']:
board[r][c]['mine'] = True
mines.add((r, c))
# Increment adjacent mine counts
for i in range(max(0, r - 1), min(height, r + 2)):
for j in range(max(0, c - 1), min(width, c + 2)):
if (i, j) != (r, c):
board[i][j]['adjacent'] += 1
return board
# === Flood Fill Reveal Logic ===
def reveal_tile(board, row, col):
if board[row][col]['revealed'] or board[row][col]['flagged']:
return
board[row][col]['revealed'] = True
# Reveal neighboring tiles recursively if no adjacent mines
if board[row][col]['adjacent'] == 0 and not board[row][col]['mine']:
for i in range(max(0, row - 1), min(len(board), row + 2)):
for j in range(max(0, col - 1), min(len(board[0]), col + 2)):
if not board[i][j]['revealed']:
reveal_tile(board, i, j)
# === Flagging ===
def toggle_flag(board, row, col):
if not board[row][col]['revealed']:
board[row][col]['flagged'] = not board[row][col]['flagged']
# === Win Condition ===
def check_win(board):
for row in board:
for tile in row:
if not tile['mine'] and not tile['revealed']:
return False
return True
# === Display Conversion ===
def cell_display(cell):
if cell['flagged']:
return "🚩"
if not cell['revealed']:
return ""
if cell['mine']:
return "πŸ’£"
return str(cell['adjacent']) if cell['adjacent'] > 0 else ""
def update_display():
return [[cell_display(cell) for cell in row] for row in game_state["board"]]
# === User Action Handler ===
def handle_click(x, y, action):
if game_state["game_over"]:
return update_display(), "Game over! Please reset."
if not (0 <= x < BOARD_WIDTH and 0 <= y < BOARD_HEIGHT):
return update_display(), "Invalid coordinates."
board = game_state["board"]
if action == "Reveal":
if board[y][x]['mine']:
board[y][x]['revealed'] = True
game_state["game_over"] = True
return update_display(), "πŸ’₯ You hit a mine! Game over."
else:
reveal_tile(board, y, x)
elif action == "Flag":
toggle_flag(board, y, x)
if check_win(board):
game_state["game_over"] = True
game_state["win"] = True
return update_display(), "πŸŽ‰ Congratulations! You won!"
return update_display(), "Continue playing..."
# === Game Reset ===
def reset_game():
game_state["board"] = initialize_board(BOARD_WIDTH, BOARD_HEIGHT, NUM_MINES)
game_state["game_over"] = False
game_state["win"] = False
return update_display(), "Game reset!"
# === Gradio UI ===
with gr.Blocks() as demo:
gr.Markdown("## 🧨 Minesweeper")
gr.Markdown("Reveal tiles and flag the mines. Good luck!")
status = gr.Textbox(label="Game Status", value="Game initialized!", interactive=False)
board_display = gr.Dataframe(value=update_display(), interactive=False, headers=None)
with gr.Row():
x_input = gr.Number(label="X (Column)", value=0, precision=0)
y_input = gr.Number(label="Y (Row)", value=0, precision=0)
action = gr.Radio(["Reveal", "Flag"], value="Reveal", label="Action")
with gr.Row():
move_btn = gr.Button("Make Move")
reset_btn = gr.Button("Reset Game")
move_btn.click(fn=handle_click, inputs=[x_input, y_input, action], outputs=[board_display, status])
reset_btn.click(fn=reset_game, outputs=[board_display, status])
# Initialize game on startup
reset_game()
demo.launch()