基于python的扫雷游戏

游戏

游戏目标:

揭开所有非地雷的格子。

如果揭开地雷,游戏失败。

使用标记功能(🚩)来标记可能的地雷位置。

格子类型:

空白格子:表示周围没有地雷。

数字格子:显示周围 8 个格子中有多少地雷。

地雷格子:揭开后游戏失败。

标记格子:玩家标记为可能的地雷位置。

操作方式:

左键点击:揭开格子。

右键点击:标记或取消标记地雷。

界面

代码

python 复制代码
import tkinter as tk
from tkinter import messagebox
import random

class Minesweeper:
    def __init__(self, root, width=10, height=10, mines=10):
        self.root = root
        self.width = width
        self.height = height
        self.mines = mines
        self.board = [[0 for _ in range(width)] for _ in range(height)]
        self.revealed = [[False for _ in range(width)] for _ in range(height)]
        self.flags = [[False for _ in range(width)] for _ in range(height)]
        self.game_over = False
        self.buttons = [[None for _ in range(width)] for _ in range(height)]
        self.remaining_mines = mines
        self.create_top_panel()
        self.place_mines()
        self.calculate_numbers()
        self.create_widgets()

    def create_top_panel(self):
        self.top_panel = tk.Frame(self.root, bg="lightgray")
        self.top_panel.grid(row=0, column=0, columnspan=self.width, sticky="ew")

        self.mine_label = tk.Label(self.top_panel, text=f"Mines: {self.remaining_mines}", font=("Arial", 12), bg="lightgray")
        self.mine_label.pack(side="left", padx=10)

        self.reset_button = tk.Button(self.top_panel, text="Reset", font=("Arial", 12), command=self.reset_game)
        self.reset_button.pack(side="right", padx=10)

    def place_mines(self):
        mines_placed = 0
        while mines_placed < self.mines:
            x = random.randint(0, self.width - 1)
            y = random.randint(0, self.height - 1)
            if self.board[y][x] != -1:
                self.board[y][x] = -1
                mines_placed += 1

    def calculate_numbers(self):
        for y in range(self.height):
            for x in range(self.width):
                if self.board[y][x] == -1:
                    continue
                count = 0
                for dy in [-1, 0, 1]:
                    for dx in [-1, 0, 1]:
                        if dy == 0 and dx == 0:
                            continue
                        ny, nx = y + dy, x + dx
                        if 0 <= ny < self.height and 0 <= nx < self.width and self.board[ny][nx] == -1:
                            count += 1
                self.board[y][x] = count

    def create_widgets(self):
        for y in range(self.height):
            for x in range(self.width):
                button = tk.Button(
                    self.root,
                    text="",
                    width=2,
                    height=1,
                    font=("Arial", 12, "bold"),
                    relief=tk.RAISED,
                    command=lambda x=x, y=y: self.reveal(x, y),
                )
                button.bind("<Button-3>", lambda event, x=x, y=y: self.toggle_flag(x, y))
                button.grid(row=y + 1, column=x, padx=1, pady=1)
                self.buttons[y][x] = button

    def reveal(self, x, y):
        if self.game_over or self.flags[y][x]:
            return
        if self.board[y][x] == -1:
            self.game_over = True
            self.buttons[y][x].config(text="💣", bg="red", relief=tk.SUNKEN)
            self.show_all_mines()
            messagebox.showinfo("Game Over", "You hit a mine! Game over.")
            return
        self.revealed[y][x] = True
        self.buttons[y][x].config(text=str(self.board[y][x]), relief=tk.SUNKEN, bg="lightgray")
        self.set_number_color(x, y)
        if self.board[y][x] == 0:
            for dy in [-1, 0, 1]:
                for dx in [-1, 0, 1]:
                    if 0 <= y + dy < self.height and 0 <= x + dx < self.width:
                        if not self.revealed[y + dy][x + dx]:
                            self.reveal(x + dx, y + dy)
        if self.check_win():
            messagebox.showinfo("Congratulations!", "You won!")

    def toggle_flag(self, x, y):
        if self.game_over or self.revealed[y][x]:
            return
        self.flags[y][x] = not self.flags[y][x]
        if self.flags[y][x]:
            self.buttons[y][x].config(text="🚩", fg="red")
            self.remaining_mines -= 1
        else:
            self.buttons[y][x].config(text="", fg="black")
            self.remaining_mines += 1
        self.mine_label.config(text=f"Mines: {self.remaining_mines}")

    def set_number_color(self, x, y):
        number = self.board[y][x]
        if number == 1:
            self.buttons[y][x].config(fg="blue")
        elif number == 2:
            self.buttons[y][x].config(fg="green")
        elif number == 3:
            self.buttons[y][x].config(fg="red")
        elif number == 4:
            self.buttons[y][x].config(fg="purple")
        elif number >= 5:
            self.buttons[y][x].config(fg="orange")

    def show_all_mines(self):
        for y in range(self.height):
            for x in range(self.width):
                if self.board[y][x] == -1:
                    self.buttons[y][x].config(text="💣", bg="yellow", relief=tk.SUNKEN)

    def check_win(self):
        for y in range(self.height):
            for x in range(self.width):
                if self.board[y][x] != -1 and not self.revealed[y][x]:
                    return False
        return True

    def reset_game(self):
        for y in range(self.height):
            for x in range(self.width):
                self.buttons[y][x].config(text="", bg="SystemButtonFace", relief=tk.RAISED, fg="black")
        self.board = [[0 for _ in range(self.width)] for _ in range(self.height)]
        self.revealed = [[False for _ in range(self.width)] for _ in range(self.height)]
        self.flags = [[False for _ in range(self.width)] for _ in range(self.height)]
        self.game_over = False
        self.remaining_mines = self.mines
        self.mine_label.config(text=f"Mines: {self.remaining_mines}")
        self.place_mines()
        self.calculate_numbers()

def main():
    root = tk.Tk()
    root.title("Minesweeper")
    game = Minesweeper(root)
    root.mainloop()

if __name__ == "__main__":
    main()
相关推荐
我爱cope11 分钟前
【从0开始学设计模式-10| 装饰模式】
java·开发语言·设计模式
2501_9142459323 分钟前
CSS如何处理CSS变量作用域冲突_利用特定类名重写变量值
jvm·数据库·python
菜鸟学Python24 分钟前
Python生态在悄悄改变:FastAPI全面反超,Django和Flask还行吗?
开发语言·python·django·flask·fastapi
<-->29 分钟前
Megatron(全称 Megatron-LM,由 NVIDIA 开发)和 DeepSpeed(由 Microsoft 开发)
人工智能·pytorch·python·深度学习·transformer
测试19981 小时前
2026最新软件测试面试八股文【附文档】
自动化测试·软件测试·python·测试工具·面试·职场和发展·测试用例
浪浪小洋1 小时前
c++ qt课设定制
开发语言·c++
charlie1145141912 小时前
嵌入式C++工程实践第16篇:第四次重构 —— LED模板,从通用GPIO到专用抽象
c语言·开发语言·c++·驱动开发·嵌入式硬件·重构
故事和你912 小时前
洛谷-数据结构1-4-图的基本应用1
开发语言·数据结构·算法·深度优先·动态规划·图论
maqr_1102 小时前
MySQL数据库迁移到云端如何保障安全_数据加密与SSL连接配置
jvm·数据库·python
u0109147602 小时前
MySQL如何限制触发器递归调用的深度_防止触发器死循环方法
jvm·数据库·python