Spaces:
Sleeping
Sleeping
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() | |