前言
又不知道该干啥了。。。。。。
开始
献上代码
from tkinter.messagebox import showinfo
from pygame.locals import *
import tkinter as tk
import random
import pygame
base = tk.Tk()
base.withdraw()
pygame.init()
WIDTH = 10
HEIGHT = 10
def generate(w,h):
res = []
for i in range(h):
ls = []
for j in range(w):
ls.append(False)
res.append(ls)
bomb_total = random.randint(1,w * h // 4)
for i in range(bomb_total):
x = random.randint(0,w - 1)
y = random.randint(0,h - 1)
res[x][y] = True
return res
def show(surf,vals):
font = pygame.font.Font('songti SC.TTF',100)
for i in range(len(vals)):
for j in range(len(vals[i])):
x1,y1,x2,y2 = i * 50,j * 50,i * 50 + 50,j * 50 + 50
rect = pygame.Rect((x1,y1,x2,y2))
if(vals[i][j] == None):
t = font.render(' ',True,(0,0,0),(255,255,255))
else:
t = font.render(str(vals[i][j]),True,(0,0,0),(255,255,255))
t = pygame.transform.scale(t,(50,50))
surf.blit(t,(50 * i,50 * j))
pygame.draw.rect(surf,(0,0,0),rect,2)
def judge(vals,puzzle):
for i in range(len(vals)):
for j in range(len(vals[i])):
if(vals[i][j] == None or (vals[i][j] == '!' and (not puzzle[j][i]))):
return False
return True
def sweep(display,puzzle,x,y,w,h):
dir = [(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1)]
def _sweep(display,puzzle,x,y,w,h):
dir = [(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1)]
display[x][y] = 0
for dx,dy in dir:
tx,ty = x + dx,y + dy
if(tx in range(h) and ty in range(w) and \
puzzle[ty][tx]):
display[x][y] += 1
return display
if(display[x][y] not in (None,'!') or puzzle[y][x]):
return display
display = _sweep(display,puzzle,x,y,w,h)
if(display[x][y] == 0):
for dx,dy in dir:
tx,ty = x + dx,y + dy
if(tx in range(h) and ty in range(w)):
display = sweep(display,puzzle,tx,ty,w,h)
return display
def main():
src = pygame.display.set_mode((50 * WIDTH,50 * HEIGHT))
puzzle = generate(WIDTH,HEIGHT)
display = []
for i in range(HEIGHT):
ls = []
for j in range(WIDTH):
ls.append(None)
display.append(ls)
while(1):
pygame.display.update()
src.fill((255,255,255))
show(src,display)
if(judge(display,puzzle)):
pygame.display.update()
showinfo('Congratulations!','Congratulations!You\'ve done it!')
exit()
for ev in pygame.event.get():
if(ev.type == QUIT):
exit()
elif(ev.type == MOUSEBUTTONDOWN):
x = ev.pos[0] // 50
y = ev.pos[1] // 50
if(ev.button == 3):
if(display[x][y] == '!'):
display[x][y] = None
else:
display[x][y] = '!'
else:
if(puzzle[y][x]):
showinfo('Failed','You click a BOMB!')
exit()
else:
display = sweep(display,puzzle,x,y,WIDTH,HEIGHT)
if(__name__ == '__main__'):
main()
代码剖析
from tkinter.messagebox import showinfo
from pygame.locals import *
import tkinter as tk
import random
import pygame
base = tk.Tk()
base.withdraw()
pygame.init()
WIDTH = 10
HEIGHT = 10
导入库及初始化,其中变量WIDTH
和HEIGHT
为方格的长和宽。
def generate(w,h):
res = []
for i in range(h):
ls = []
for j in range(w):
ls.append(False)
res.append(ls)
bomb_total = random.randint(1,w * h // 4)
for i in range(bomb_total):
x = random.randint(0,w - 1)
y = random.randint(0,h - 1)
res[x][y] = True
return res
随机生成地雷,其中
bomb_total = random.randint(1,w * h // 4)
中的
1
可以更改成任意小于等于方格数的数字,表示地雷的最小个数w * h // 4
可以更改为任意小于等于方格数的数字,表示地雷的最大个数
def show(surf,vals):
font = pygame.font.Font('songti SC.TTF',100)
for i in range(len(vals)):
for j in range(len(vals[i])):
x1,y1,x2,y2 = i * 50,j * 50,i * 50 + 50,j * 50 + 50
rect = pygame.Rect((x1,y1,x2,y2))
if(vals[i][j] == None):
t = font.render(' ',True,(0,0,0),(255,255,255))
else:
t = font.render(str(vals[i][j]),True,(0,0,0),(255,255,255))
t = pygame.transform.scale(t,(50,50))
surf.blit(t,(50 * i,50 * j))
pygame.draw.rect(surf,(0,0,0),rect,2)
这里与2048游戏中我使用的代码类似,其中增加的三行代码以及更改的几个数字的解释如下:
增加的几行为
x1,y1,x2,y2 = i * 50,j * 50,i * 50 + 50,j * 50 + 50
rect = pygame.Rect((x1,y1,x2,y2))
// ......
pygame.draw.rect(surf,(0,0,0),rect,2)
解释如下:
- 第一行,定义画矩形的位置。
(x1,y1)
为第一组坐标,左上角。(x2,y2)
为第二组坐标,右下角。示意图如下: - 第二行,根据两组坐标确定一个
pygame.Rect
位置描述对象 - 第三行,根据第二行产生的位置描述对象画一个矩形
这样重复,就可以产生一个网格
更改的整数表示字符大小,尽量不要随意改变。
def judge(vals,puzzle):
for i in range(len(vals)):
for j in range(len(vals[i])):
if(vals[i][j] == None or (vals[i][j] == '!' and (not puzzle[j][i]))):
return False
return True
判断游戏是否成功
这里认为满足如下两点的所有状态都可以认为游戏成功:
- 没有空格
- 所有!背后都是炸弹
def sweep(display,puzzle,x,y,w,h):
dir = [(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1)]
def _sweep(display,puzzle,x,y,w,h):
dir = [(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1)]
display[x][y] = 0
for dx,dy in dir:
tx,ty = x + dx,y + dy
if(tx in range(h) and ty in range(w) and \
puzzle[ty][tx]):
display[x][y] += 1
return display
if(display[x][y] not in (None,'!') or puzzle[y][x]):
return display
display = _sweep(display,puzzle,x,y,w,h)
if(display[x][y] == 0):
for dx,dy in dir:
tx,ty = x + dx,y + dy
if(tx in range(h) and ty in range(w)):
display = sweep(display,puzzle,tx,ty,w,h)
return display
使用类似深度优先搜索的方式实现点击效果
至于深度优先搜索是啥算法,出门左转百度
def main():
src = pygame.display.set_mode((50 * WIDTH,50 * HEIGHT))
puzzle = generate(WIDTH,HEIGHT)
display = []
for i in range(HEIGHT):
ls = []
for j in range(WIDTH):
ls.append(None)
display.append(ls)
while(1):
pygame.display.update()
src.fill((255,255,255))
show(src,display)
if(judge(display,puzzle)):
pygame.display.update()
showinfo('Congratulations!','Congratulations!You\'ve done it!')
exit()
for ev in pygame.event.get():
if(ev.type == QUIT):
exit()
elif(ev.type == MOUSEBUTTONDOWN):
x = ev.pos[0] // 50
y = ev.pos[1] // 50
if(ev.button == 3):
if(display[x][y] == '!'):
display[x][y] = None
else:
display[x][y] = '!'
else:
if(puzzle[y][x]):
showinfo('Failed','You click a BOMB!')
exit()
else:
display = sweep(display,puzzle,x,y,WIDTH,HEIGHT)
这里分开剖析
def main():
src = pygame.display.set_mode((50 * WIDTH,50 * HEIGHT))
puzzle = generate(WIDTH,HEIGHT)
display = []
for i in range(HEIGHT):
ls = []
for j in range(WIDTH):
ls.append(None)
display.append(ls)
初始化变量:
src
为窗口对象puzzle
为炸弹的分布情况display
为显示情况
while(1):
pygame.display.update()
src.fill((255,255,255))
show(src,display)
if(judge(display,puzzle)):
pygame.display.update()
showinfo('Congratulations!','Congratulations!You\'ve done it!')
exit()
刷新窗口,判断游戏结束
for ev in pygame.event.get():
if(ev.type == QUIT):
exit()
事件循环开始,判断关闭窗口事件
elif(ev.type == MOUSEBUTTONDOWN):
x = ev.pos[0] // 50
y = ev.pos[1] // 50
if(ev.button == 3):
if(display[x][y] == '!'):
display[x][y] = None
else:
display[x][y] = '!'
判断右键键标记炸弹
else:
if(puzzle[y][x]):
showinfo('Failed','You click a BOMB!')
exit()
else:
display = sweep(display,puzzle,x,y,WIDTH,HEIGHT)
判断左键展示数字,踩雷扫雷结束游戏
if(__name__ == '__main__'):
main()
运行游戏
项目github
作者
hit-road
拜拜,下课!
hit-road不定期跟新,不见不散!