游戏
游戏目标:
揭开所有非地雷的格子。
如果揭开地雷,游戏失败。
使用标记功能(🚩)来标记可能的地雷位置。
格子类型:
空白格子:表示周围没有地雷。
数字格子:显示周围 8 个格子中有多少地雷。
地雷格子:揭开后游戏失败。
标记格子:玩家标记为可能的地雷位置。
操作方式:
左键点击:揭开格子。
右键点击:标记或取消标记地雷。
界面
代码
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()