(文章最后是完整代码)大家如果对代码有什么疑问也可以私信我,乐意解答
效果如下:
因为追求简洁简单,所以界面也简介,其中❓输入法里面都有
首先定义一些边框大小
LABLE_LEN = 30 #格子大小
LABLE_cow = 15 #各自多少行
LABLE_lis = 30 #格子多少列
TIME_HIGHT = 40 #按钮和时间的高度
MAIN_WEIGHT = LABLE_lis*LABLE_LEN#主界面大小
MAIN_HIGHT = LABLE_cow*LABLE_LEN+TIME_HIGHT
GAME_HIGHT=LABLE_cow*LABLE_LEN
界面布局
①主界面
#1.定义主界面
root = Tk()
root.minsize(MAIN_WEIGHT, MAIN_HIGHT) # 最小尺寸
root.maxsize(MAIN_WEIGHT, MAIN_HIGHT) # 最大尺寸
②设置界面:里面的newgame方法后面会介绍
setframe = Frame(root,height=TIME_HIGHT,width=MAIN_WEIGHT)
setframe.grid_location(0,0)
setframe.pack()
#2.1开始游戏按钮
newgame_button = Button(setframe,text= '新游戏',fg= 'blue',command=newgame)#事件尚未添加
newgame_button.grid(row=0,column=0,padx=10,pady=5)
#2.2游戏时间
time_start=time.time()
time_var = StringVar()
time_var.set('')
time_lable = Label(setframe,textvariable=time_var,width=50)
time_lable.grid(row=0,column=1,padx=10,pady=5)
#2.3退出按钮
quit_buttton = Button(setframe,text= '退出游戏',fg= 'blue',command=quit)
quit_buttton.grid(row=0,column=2,padx=10,pady=5)
③游戏界面设置
#3游戏界面
game_frame = Frame(root,width=MAIN_WEIGHT,height=GAME_HIGHT)
game_frame.place(x=0,y=TIME_HIGHT)
grids = Grids(game_frame=game_frame,LABLE_LEN=LABLE_LEN)
update_clock()
root.mainloop()
为了实现以下图片效果,可以选择在frame控件上添加label,label设置边框就可以轻松实现。为了方便也创建一个Grids类
格子类的初始化函数
def __init__(self,game_frame,LABLE_LEN):
self.game_frame = game_frame
for i in range(15):
for j in range(30):
var = StringVar()
var.set('')
self.num.append(0)
self.num_var.append(var)
self.stats.append(0)
la = Label(game_frame,height=LABLE_LEN,width=LABLE_LEN,borderwidth=1,relief='ridge',textvariable=var)
la.place(x=j*LABLE_LEN,y=i*LABLE_LEN,width=LABLE_LEN, height=LABLE_LEN)
la.bind("" , zuo_button)
la.bind("" , you_buttton)
self.lables.append(la)
self.newgame()
下面函数的功能介绍
①新游戏功能
def newgame():
grids.newgame()
global time_start
time_start = time.time()
通过这个外面函数通知Grids里面的newgame进行参数设置也就是初始化
def newgame(self):
for i in range(15):
for j in range(30):
self.num[i*30+j]=0
self.stats[i*30+j]=0
self.num_var[i*30+j].set('')
self.lables[i*30+j].configure(bg='yellow')
self.flag = 0
self.num_kai = 0
self.produce()
self.count()
pass
②鼠标左击点击事件:为了知道点击了哪一个lable,我想了一个比较巧妙的方法
由于只能获取 event的x,y,root_x等参数,无法获取准确的第几块lable
所以 首先获取主界面位于屏幕的位置
fx = root.winfo_x()
然后正确的lable位于主界面的位置如下
x = event.x_root-fx-7
然后进行求余操作
x = x//LABLE_LEN
就可以知道点击了第几列的lable
同样对y进行操作也可以知道点击了第几行,那么就可以定位了
完整代码如下
def zuo_button(event):
fx = root.winfo_x()
fy = root.winfo_y()
x = event.x_root-fx-7
y = event.y_root-fy-TIME_HIGHT-30
x = x//LABLE_LEN
y = y//LABLE_LEN
grids.zuo_button(y,x)
grids里的左击点击事件
def zuo_button(self,i,j):
if self.flag==1:
return
#判断界限,或结束游戏,或已经开牌
if not(0<=i<=14 and 0<=j<=29) :
return
if self.stats[i*30+j]==3:
#开牌了的话,计算周围棋子数,棋子数与数字一样则打开这个棋子周围全部
if self.num[i*30+j]==0:
return
else:self.drawqizi(i,j)
if self.num[i*30+j]==10:#翻到炸弹
print('炸弹')
self.flag=1
self.showzhadan()
return
else:
self.draw(i,j)
pass
③递归翻拍
def draw(self,i,j):
if not(0<=i<=14 and 0<=j<=29) or self.stats[i*30+j]==3:#越界
return
elif 0<self.num[i*30+j]<10:#数字
self.num_var[i*30+j].set(self.num[i*30+j])
self.lables[i*30+j].configure(bg='white')
self.stats[i * 30 + j] = 3
self.num_kai = self.num_kai + 1
print(self.num_kai)
if self.num_kai >= self.num_all - self.num_zhadan:
self.flag = 1
time_var.set('你赢了!!')
else:
self.num_var[i * 30 + j].set('')
self.lables[i * 30 + j].configure(bg='white')
self.stats[i * 30 + j] = 3
for f in self.fix:
li, lj = f
lx = i - li
ly = j - lj
self.draw(lx,ly)
self.num_kai = self.num_kai + 1
print(self.num_kai)
if self.num_kai >= self.num_all - self.num_zhadan:
self.flag = 1
time_var.set('你赢了!!')
④鼠标右击插旗和打问号
def you_buttton(event):
fx = root.winfo_x()
fy = root.winfo_y()
x = event.x_root - fx - 7
y = event.y_root - fy - TIME_HIGHT - 30
x = x // LABLE_LEN
y = y // LABLE_LEN
grids.you_button(y, x)
grids里面的右击插旗和打问号
def you_button(self,i,j):
if self.stats[i*30+j]!=3:
self.stats[i*30+j] = (self.stats[i*30+j]+1)%3
self.num_var[i*30+j].set(self.str[self.stats[i*30+j]])
pass
还有一些产生炸弹和计算周围炸弹数量的函数
def produce(self):#随机生成炸弹
self.zhadans = random.sample(range(0, 30*15-1), self.num_zhadan)
for zhadan in self.zhadans:
i = zhadan//30
j = zhadan%30
self.num[zhadan]=10
def count(self):#计算周围炸弹
self.fix = [(-1,-1),(0,-1),(1,-1),(-1,0),(1,0),(-1,1),(0,1),(1,1)]#八个方向
for i in range(15):
for j in range(30):
if self.num[i*30+j]==10:
continue
for f in self.fix:
li, lj = f
lx = i-li
ly = j-lj
if 0<=lx<=14 and 0<=ly<=29 and self.num[lx*30+ly]==10:
self.num[i * 30 + j] = self.num[i * 30 + j]+1
pass
完整代码:
from tkinter import *
import random
import time
"""
格子类
"""
def zuo_button(event):
fx = root.winfo_x()
fy = root.winfo_y()
x = event.x_root-fx-7
y = event.y_root-fy-TIME_HIGHT-30
x = x//LABLE_LEN
y = y//LABLE_LEN
grids.zuo_button(y,x)
def you_buttton(event):
fx = root.winfo_x()
fy = root.winfo_y()
x = event.x_root - fx - 7
y = event.y_root - fy - TIME_HIGHT - 30
x = x // LABLE_LEN
y = y // LABLE_LEN
grids.you_button(y, x)
pass
def newgame():
grids.newgame()
global time_start
time_start = time.time()
def update_clock():
end_time = time.time()
t = round(end_time-time_start)
global grids
if grids.flag==0:
time_var.set(t)
root.after(1000, update_clock)
class Grids:
flag = 0
num_zhadan = 70
num_all = 30*15
num_kai = 0
num = [] #01,2,3,4,5,6,7,8, 10表示炸弹
stats=[] #0没有1棋子2问号3打开
str=["","","❓"]
lables = []
num_var = []
game_frame=None
def produce(self):#随机生成炸弹
self.zhadans = random.sample(range(0, 30*15-1), self.num_zhadan)
for zhadan in self.zhadans:
i = zhadan//30
j = zhadan%30
self.num[zhadan]=10
def count(self):#计算周围炸弹
self.fix = [(-1,-1),(0,-1),(1,-1),(-1,0),(1,0),(-1,1),(0,1),(1,1)]#八个方向
for i in range(15):
for j in range(30):
if self.num[i*30+j]==10:
continue
for f in self.fix:
li, lj = f
lx = i-li
ly = j-lj
if 0<=lx<=14 and 0<=ly<=29 and self.num[lx*30+ly]==10:
self.num[i * 30 + j] = self.num[i * 30 + j]+1
pass
def newgame(self):
for i in range(15):
for j in range(30):
self.num[i*30+j]=0
self.stats[i*30+j]=0
self.num_var[i*30+j].set('')
self.lables[i*30+j].configure(bg='yellow')
self.flag = 0
self.num_kai = 0
self.produce()
self.count()
pass
def showzhadan(self):
for zhadan in self.zhadans:
self.num_var[zhadan].set('')
pass
def draw(self,i,j):
if not(0<=i<=14 and 0<=j<=29) or self.stats[i*30+j]==3:#越界
return
elif 0<self.num[i*30+j]<10:#数字
self.num_var[i*30+j].set(self.num[i*30+j])
self.lables[i*30+j].configure(bg='white')
self.stats[i * 30 + j] = 3
self.num_kai = self.num_kai + 1
print(self.num_kai)
if self.num_kai >= self.num_all - self.num_zhadan:
self.flag = 1
time_var.set('你赢了!!')
else:
self.num_var[i * 30 + j].set('')
self.lables[i * 30 + j].configure(bg='white')
self.stats[i * 30 + j] = 3
for f in self.fix:
li, lj = f
lx = i - li
ly = j - lj
self.draw(lx,ly)
self.num_kai = self.num_kai + 1
print(self.num_kai)
if self.num_kai >= self.num_all - self.num_zhadan:
self.flag = 1
time_var.set('你赢了!!')
def drawqizi(self,i,j):
count = 0
for f in self.fix:
li, lj = f
lx = i - li
ly = j - lj
if 0 <= lx <= 14 and 0 <= ly <= 29 and self.stats[lx * 30 + ly] == 1:
count = count+1
if count==self.num[i*30+j]:
print('kai')
#打开八个方向除了插了的格子
for f in self.fix:
li, lj = f
lx = i - li
ly = j - lj
if 0 <= lx <= 14 and 0 <= ly <= 29 and self.stats[lx * 30 + ly] != 1 and self.stats[lx * 30 + ly] != 3:#状态不是的话就开
if self.num[lx*30+ly]==10:#开到炸弹游戏结束
self.flag=1
time_var.set('踩雷了!!')
self.showzhadan()
return
else:
# self.num_var[lx * 30 + ly].set(self.num[lx * 30 + ly])
# self.lables[lx * 30 + ly].configure(bg='white')
# self.stats[lx * 30 + ly] = 3
# self.num_kai = self.num_kai + 1
# print(self.num_kai)
# if self.num_kai >= self.num_all - self.num_zhadan:
# self.flag = 1
# time_var.set('你赢了!!')
self.draw(lx,ly)
def zuo_button(self,i,j):
if self.flag==1:
return
#判断界限,或结束游戏,或已经开牌
if not(0<=i<=14 and 0<=j<=29) :
return
if self.stats[i*30+j]==3:
#开牌了的话,计算周围棋子数,棋子数与数字一样则打开这个棋子周围全部
if self.num[i*30+j]==0:
return
else:self.drawqizi(i,j)
if self.num[i*30+j]==10:#翻到炸弹
print('炸弹')
self.flag=1
self.showzhadan()
return
else:
self.draw(i,j)
pass
def you_button(self,i,j):
if self.stats[i*30+j]!=3:
self.stats[i*30+j] = (self.stats[i*30+j]+1)%3
self.num_var[i*30+j].set(self.str[self.stats[i*30+j]])
pass
def __init__(self,game_frame,LABLE_LEN):
self.game_frame = game_frame
for i in range(15):
for j in range(30):
var = StringVar()
var.set('')
self.num.append(0)
self.num_var.append(var)
self.stats.append(0)
la = Label(game_frame,height=LABLE_LEN,width=LABLE_LEN,borderwidth=1,relief='ridge',textvariable=var)
la.place(x=j*LABLE_LEN,y=i*LABLE_LEN,width=LABLE_LEN, height=LABLE_LEN)
la.bind("" , zuo_button)
la.bind("" , you_buttton)
self.lables.append(la)
self.newgame()
"""
设置界面大小参数
"""
LABLE_LEN = 30 #格子大小
LABLE_cow = 15 #各自多少行
LABLE_lis = 30 #格子多少列
TIME_HIGHT = 40 #按钮和时间的高度
MAIN_WEIGHT = LABLE_lis*LABLE_LEN#主界面大小
MAIN_HIGHT = LABLE_cow*LABLE_LEN+TIME_HIGHT
GAME_HIGHT=LABLE_cow*LABLE_LEN
#1.定义主界面
root = Tk()
root.minsize(MAIN_WEIGHT, MAIN_HIGHT) # 最小尺寸
root.maxsize(MAIN_WEIGHT, MAIN_HIGHT) # 最大尺寸
#2.定义游戏设置界面:开始按钮,结束按钮,时间
setframe = Frame(root,height=TIME_HIGHT,width=MAIN_WEIGHT)
setframe.grid_location(0,0)
setframe.pack()
#2.1开始游戏按钮
newgame_button = Button(setframe,text= '新游戏',fg= 'blue',command=newgame)#事件尚未添加
newgame_button.grid(row=0,column=0,padx=10,pady=5)
#2.2游戏时间
time_start=time.time()
time_var = StringVar()
time_var.set('')
time_lable = Label(setframe,textvariable=time_var,width=50)
time_lable.grid(row=0,column=1,padx=10,pady=5)
#2.3退出按钮
quit_buttton = Button(setframe,text= '退出游戏',fg= 'blue',command=quit)
quit_buttton.grid(row=0,column=2,padx=10,pady=5)
#3游戏界面
game_frame = Frame(root,width=MAIN_WEIGHT,height=GAME_HIGHT)
game_frame.place(x=0,y=TIME_HIGHT)
grids = Grids(game_frame=game_frame,LABLE_LEN=LABLE_LEN)
update_clock()
root.mainloop()