无聊时可用此小游戏打发无聊时光。
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()