扫雷小游戏,可打发无聊时光

无聊时可用此小游戏打发无聊时光。

import tkinter as tk
from tkinter import messagebox
import random

class Minesweeper:
    """
    扫雷游戏主类
    """

    def __init__(self, master, rows=10, cols=10, mines=10):
        """
        初始化游戏参数和界面
        :param master: Tkinter主窗口对象
        :param rows: 游戏行数
        :param cols: 游戏列数
        :param mines: 地雷数量
        """
        self.master = master
        self.rows = rows
        self.cols = cols
        self.mines = mines
        self.board = [[0 for _ in range(cols)] for _ in range(rows)]
        self.buttons = [[None for _ in range(cols)] for _ in range(rows)]
        self.flags = set()
        self.revealed = set()
        self.game_over = False

        self.place_mines()
        self.calculate_numbers()

        self.create_widgets()
        self.add_control_buttons()

    def place_mines(self):
        """
        随机放置地雷
        """
        positions = [(r, c) for r in range(self.rows) for c in range(self.cols)]
        mine_positions = random.sample(positions, self.mines)
        for r, c in mine_positions:
            self.board[r][c] = -1

    def calculate_numbers(self):
        """
        计算每个非地雷单元格周围的地雷数
        """
        for r in range(self.rows):
            for c in range(self.cols):
                if self.board[r][c] == -1:
                    continue
                count = sum(
                    1 for nr, nc in self.get_neighbors(r, c) if self.board[nr][nc] == -1
                )
                self.board[r][c] = count

    def get_neighbors(self, r, c):
        """
        获取指定单元格的所有邻居单元格
        :param r: 行索引
        :param c: 列索引
        :return: 邻居单元格的列表
        """
        neighbors = []
        for dr in [-1, 0, 1]:
            for dc in [-1, 0, 1]:
                nr, nc = r + dr, c + dc
                if 0 <= nr < self.rows and 0 <= nc < self.cols:
                    neighbors.append((nr, nc))
        return neighbors

    def create_widgets(self):
        """
        创建游戏按钮
        """
        for r in range(self.rows):
            for c in range(self.cols):
                button = tk.Button(
                    self.master,
                    width=2,
                    height=1,
                    font=("Arial", 12),
                    command=lambda r=r, c=c: self.on_click(r, c),
                )
                button.bind("<Button-3>", lambda event, r=r, c=c: self.toggle_flag(r, c))
                button.grid(row=r, column=c)
                self.buttons[r][c] = button

    def add_control_buttons(self):
        """
        添加控制按钮:重新开始和结束游戏
        """
        restart_button = tk.Button(self.master, text="重新开始", command=self.restart_game)
        restart_button.grid(row=self.rows, column=0, columnspan=self.cols//2, sticky="ew")
        quit_button = tk.Button(self.master, text="结束游戏", command=self.master.quit)
        quit_button.grid(row=self.rows, column=self.cols//2, columnspan=self.cols-self.cols//2, sticky="ew")

    def on_click(self, r, c):
        """
        处理左键点击事件
        :param r: 行索引
        :param c: 列索引
        """
        if (r, c) in self.flags or self.game_over:
            return
        if self.board[r][c] == -1:
            self.show_all()
            messagebox.showinfo("游戏结束", "你打了个地雷!")
            self.game_over = True
        else:
            self.reveal(r, c)

    def reveal(self, r, c):
        """
        揭示单元格
        :param r: 行索引
        :param c: 列索引
        """
        if (r, c) in self.revealed:
            return
        self.revealed.add((r, c))
        button = self.buttons[r][c]
        value = self.board[r][c]
        if value > 0:
            button.config(text=str(value), state=tk.DISABLED, bg="gray", fg="yellow")
        elif value == 0:
            button.config(state=tk.DISABLED, bg="gray")
            for nr, nc in self.get_neighbors(r, c):
                self.reveal(nr, nc)
        self.check_win()

    def toggle_flag(self, r, c):
        """
        处理右键点击事件,切换旗帜
        :param r: 行索引
        :param c: 列索引
        """
        if self.game_over:
            return
        button = self.buttons[r][c]
        if (r, c) not in self.revealed:
            if (r, c) in self.flags:
                self.flags.remove((r, c))
                button.config(text="")
            else:
                self.flags.add((r, c))
                button.config(text="F")

    def show_all(self):
        """
        游戏结束时展示所有单元格
        """
        for r in range(self.rows):
            for c in range(self.cols):
                button = self.buttons[r][c]
                if self.board[r][c] == -1:
                    button.config(text="*", bg="red", fg="white")
                elif self.board[r][c] > 0:
                    button.config(text=str(self.board[r][c]), state=tk.DISABLED, bg="gray", fg="yellow")
                else:
                    button.config(state=tk.DISABLED, bg="gray")

    def check_win(self):
        """
        检查是否赢得游戏
        """
        if len(self.revealed) == self.rows * self.cols - self.mines:
            self.show_all()
            messagebox.showinfo("恭喜您!", "您赢得了游戏!")
            self.game_over = True

    def restart_game(self):
        """
        重新开始游戏
        """
        self.game_over = False
        self.flags.clear()
        self.revealed.clear()
        self.board = [[0 for _ in range(self.cols)] for _ in range(self.rows)]
        self.buttons = [[None for _ in range(self.cols)] for _ in range(self.rows)]
        self.place_mines()
        self.calculate_numbers()
        for r in range(self.rows):
            for c in range(self.cols):
                if self.buttons[r][c]:
                    self.buttons[r][c].destroy()
        self.create_widgets()


if __name__ == "__main__":
    root = tk.Tk()
    root.title("Minesweeper")
    game = Minesweeper(root)
    root.mainloop()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值