【python小游戏】扫雷

发布于:2025-03-24 ⋅ 阅读:(45) ⋅ 点赞:(0)

扫雷小游戏代码。供消遣娱乐: 

import tkinter as tk
from tkinter import messagebox
import random

# 游戏参数(中等难度:15x15 网格,40 颗雷)
ROWS = 15
COLS = 15
MINES = 40
CELL_SIZE = 30
COLORS = {
    'default': '#CCCCCC',
    'opened': '#FFFFFF',
    'mine': '#FF0000',
    'flag': '#00FF00',
    'text': '#000000'
}

class Minesweeper:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("扫雷游戏 - 中级")
        self.board = []
        self.mines = set()
        self.flags = set()
        self.opened = set()
        self.game_over = False
        self.start_time = None
        self.timer = 0

        # 初始化界面
        self.create_widgets()
        self.generate_mines()
        self.update_timer()
        self.window.mainloop()

    def create_widgets(self):
        self.timer_label = tk.Label(self.window, text="时间: 0", font=('Arial', 12))
        self.timer_label.grid(row=0, column=0, columnspan=COLS)

        self.mine_label = tk.Label(self.window, text=f"剩余雷数: {MINES}", font=('Arial', 12))
        self.mine_label.grid(row=0, column=COLS-2, columnspan=2)

        self.canvas = tk.Canvas(self.window, width=COLS*CELL_SIZE, height=ROWS*CELL_SIZE)
        self.canvas.grid(row=1, column=0, columnspan=COLS)

        # 绘制网格
        for x in range(COLS):
            for y in range(ROWS):
                self.board.append((x, y))
                self.canvas.create_rectangle(
                    x*CELL_SIZE, y*CELL_SIZE,
                    (x+1)*CELL_SIZE, (y+1)*CELL_SIZE,
                    fill=COLORS['default'], outline='black'
                )

        self.canvas.bind('<Button-1>', self.left_click)
        self.canvas.bind('<Button-3>', self.right_click)

    def generate_mines(self):
        self.mines = set(random.sample(self.board, MINES))

    def count_nearby_mines(self, x, y):
        count = 0
        for dx in (-1, 0, 1):
            for dy in (-1, 0, 1):
                if (dx, dy) == (0, 0):
                    continue
                if (x+dx, y+dy) in self.mines:
                    count += 1
        return count

    def left_click(self, event):
        if self.game_over:
            return
        if not self.start_time:
            self.start_time = True
            self.window.after(1000, self.update_timer)

        x = event.x // CELL_SIZE
        y = event.y // CELL_SIZE
        cell = (x, y)

        if cell in self.flags:
            return

        if cell in self.mines:
            self.game_over = True
            self.reveal_mines()
            messagebox.showerror("游戏结束", "你踩到地雷了!")
            self.window.destroy()
        else:
            self.open_cell(x, y)

    def right_click(self, event):
        if self.game_over:
            return
        x = event.x // CELL_SIZE
        y = event.y // CELL_SIZE
        cell = (x, y)

        if cell in self.opened:
            return

        if cell in self.flags:
            self.flags.remove(cell)
            self.canvas.itemconfig(self.get_cell_id(x, y), fill=COLORS['default'])
        else:
            self.flags.add(cell)
            self.canvas.itemconfig(self.get_cell_id(x, y), fill=COLORS['flag'])

        self.mine_label.config(text=f"剩余雷数: {MINES - len(self.flags)}")

    def open_cell(self, x, y):
        if (x, y) in self.opened:
            return
        self.opened.add((x, y))

        count = self.count_nearby_mines(x, y)
        cell_id = self.get_cell_id(x, y)
        self.canvas.itemconfig(cell_id, fill=COLORS['opened'])

        if count > 0:
            self.canvas.create_text(
                x*CELL_SIZE + CELL_SIZE//2,
                y*CELL_SIZE + CELL_SIZE//2,
                text=str(count), fill=COLORS['text'], font=('Arial', 12)
            )
        else:
            # 递归打开相邻空白格
            for dx in (-1, 0, 1):
                for dy in (-1, 0, 1):
                    nx, ny = x+dx, y+dy
                    if 0 <= nx < COLS and 0 <= ny < ROWS:
                        self.open_cell(nx, ny)

        if len(self.opened) + MINES == ROWS*COLS:
            messagebox.showinfo("胜利", "你成功排除了所有地雷!")
            self.window.destroy()

    def get_cell_id(self, x, y):
        return self.canvas.find_closest(x*CELL_SIZE + CELL_SIZE//2, y*CELL_SIZE + CELL_SIZE//2)[0]

    def reveal_mines(self):
        for (x, y) in self.mines:
            self.canvas.itemconfig(self.get_cell_id(x, y), fill=COLORS['mine'])

    def update_timer(self):
        if self.start_time and not self.game_over:
            self.timer += 1
            self.timer_label.config(text=f"时间: {self.timer}")
            self.window.after(1000, self.update_timer)

if __name__ == "__main__":
    Minesweeper()