python用tkinter程序做扫雷游戏代码有注释
以下是Python用tkinter程序做扫雷游戏的代码,带有注释,方便理解:
import tkinter as tk
import random
# 定义常量
MINE = 10
SIZE = 30
WIDTH = 9
HEIGHT = 9
class MineSweeper:
def __init__(self):
# 创建主窗口
self.root = tk.Tk()
self.root.title('扫雷游戏')
self.root.resizable(width=False, height=False)
# 创建游戏区域
self.canvas = tk.Canvas(self.root,
width=WIDTH*SIZE,
height=HEIGHT*SIZE)
self.canvas.pack()
# 初始化游戏
self.init_game()
# 绑定事件
self.canvas.bind('<Button-1>', self.left_click)
self.canvas.bind('<Button-3>', self.right_click)
self.canvas.bind('<Button-2>', self.init_game)
# 进入主循环
self.root.mainloop()
def init_game(self, event=None):
# 清空游戏区域
self.canvas.delete('all')
# 初始化状态数组
self.status = [[0 for j in range(WIDTH)] for i in range(HEIGHT)]
# 随机布雷
self.mines = []
while len(self.mines) < MINE:
mine = (random.randint(0, WIDTH-1), random.randint(0, HEIGHT-1))
if mine not in self.mines:
self.mines.append(mine)
# 绘制格子
for i in range(HEIGHT):
for j in range(WIDTH):
x1, y1 = j*SIZE, i*SIZE
x2, y2 = x1+SIZE, y1+SIZE
self.canvas.create_rectangle(x1, y1, x2, y2, fill='gray')
# 绘制雷
for mine in self.mines:
x1, y1 = mine[0]*SIZE, mine[1]*SIZE
x2, y2 = x1+SIZE, y1+SIZE
self.canvas.create_oval(x1+3, y1+3, x2-3, y2-3, fill='black')
# 更新状态数组
for mine in self.mines:
for i in range(mine[1]-1, mine[1]+2):
for j in range(mine[0]-1, mine[0]+2):
if i<0 or j<0 or i>=HEIGHT or j>=WIDTH or (i,j) in self.mines:
continue
self.status[i][j] += 1
def left_click(self, event):
# 获取点击位置
x, y = event.x//SIZE, event.y//SIZE
# 如果点到雷,游戏结束
if (x, y) in self.mines:
self.game_over()
# 如果点到空白格子,递归展开周围的格子
elif self.status[y][x] == 0:
self.canvas.create_rectangle(x*SIZE, y*SIZE, (x+1)*SIZE, (y+1)*SIZE, fill='white')
self.status[y][x] = -1
for i in range(y-1, y+2):
for j in range(x-1, x+2):
if i<0 or j<0 or i>=HEIGHT or j>=WIDTH or self.status[i][j] != 0:
continue
self.left_click(tk.Event(type='Button-1', x=(j+0.5)*SIZE, y=(i+0.5)*SIZE))
# 如果点到数字格子,展示数字
else:
self.canvas.create_text((x+0.5)*SIZE, (y+0.5)*SIZE, text=str(self.status[y][x]))
# 检查游戏是否胜利
self.check_win()
def right_click(self, event):
# 获取点击位置
x, y = event.x//SIZE, event.y//SIZE
# 如果是未翻开的格子,标记为雷
if self.status[y][x] == 0:
self.canvas.create_text((x+0.5)*SIZE, (y+0.5)*SIZE, text='X', fill='red')
self.status[y][x] = -2
# 如果是已标记的格子,取消标记
elif self.status[y][x] == -2:
self.canvas.create_rectangle(x*SIZE, y*SIZE, (x+1)*SIZE, (y+1)*SIZE, fill='gray')
self.status[y][x] = 0
# 检查游戏是否胜利
self.check_win()
def game_over(self):
# 展示所有雷的位置
for mine in self.mines:
x1, y1 = mine[0]*SIZE, mine[1]*SIZE
x2, y2 = x1+SIZE, y1+SIZE
self.canvas.create_oval(x1+3, y1+3, x2-3, y2-3, fill='red')
# 弹出游戏结束的提示框
tk.messagebox.showinfo('游戏结束', '很遗憾,你输了!')
def check_win(self):
# 判断游戏是否胜利
for i in range(HEIGHT):
for j in range(WIDTH):
if self.status[i][j] == 0:
return
tk.messagebox.showinfo('游戏结束', '恭喜你,你赢了!')
# 启动游戏
if __name__ == '__main__':
minesweeper = MineSweeper()
在代码中,我们首先定义了一些常量,包括:
MINE:雷的数量SIZE:每个格子的大小WIDTH:游戏区域的宽度(格子数)HEIGHT:游戏区域的高度(格子数)
然后,我们定义了一个 MineSweeper 类,表示扫雷游戏。在类的 __init__() 方法中,我们创建了主窗口、游戏区域,初始化游戏,并绑定了鼠标事件。
在 init_game() 方法中,我们清空游戏区域,初始化状态数组,随机布雷,绘制格子和雷,并更新状态数组。
在 left_click() 方法中,我们获取点击位置,判断是否点到雷、空白格子或数字格子,并做出相应的反应。如果点到空白格子,我们递归展开周围的格子,直到遇到数字格子或边界。如果点到数字格子,我们展示数字。最后,我们检查游戏是否胜利,如果胜利,弹出提示框。
在 right_click() 方法中,我们获取点击位置,判断格子的状态,并做出相应的反应。如果格子未翻开,我们标记为雷;如果格子已标记,我们取消标记。最后,我们检查游戏是否胜利,如果胜利,弹出提示框。
在 game_over() 方法中,我们展示所有雷的位置,并弹出游戏结束的提示框。
在 check_win() 方法中,我们判断游戏是否胜利。如果所有空白格子和数字格子都已翻开,游戏胜利。
最后,我们在 __main__ 中启动游戏
原文地址: https://www.cveoy.top/t/topic/eE07 著作权归作者所有。请勿转载和采集!