|
|
import tkinter
|
|
|
import tkinter.messagebox
|
|
|
import random
|
|
|
|
|
|
return_value1 = tkinter.messagebox.askyesnocancel('进入游戏', '请合理安排游戏时间')
|
|
|
if return_value1 == True:
|
|
|
print("good luck祝您玩的开心")
|
|
|
else:
|
|
|
return_value2 = tkinter.messagebox.askyesno('进入游戏', '您真的退出游戏吗?')
|
|
|
if return_value2==True:
|
|
|
print("您取消了进入游戏")
|
|
|
exit()
|
|
|
else:
|
|
|
print("good luck祝您玩的开心")
|
|
|
|
|
|
|
|
|
# 通过路径获取图片
|
|
|
def get_image(filename, w=None, h=None):
|
|
|
try:
|
|
|
im = tkinter.PhotoImage(file=filename)
|
|
|
if w != None and h != None:
|
|
|
im = im.subsample(im.width() // w, im.height() // h)
|
|
|
return im
|
|
|
except:
|
|
|
return None
|
|
|
|
|
|
class Sweep(tkinter.Button):
|
|
|
map = [] # 地图
|
|
|
w = 7 # 地图宽度
|
|
|
h = 8 # 地图高度
|
|
|
mine = 5 # 地雷个数
|
|
|
x0 = 30 # 地图相对于主窗口的起点
|
|
|
y0 = 50
|
|
|
count = 0 # 扫除计数
|
|
|
state = 0 # 0play 1vectroy 2over 游戏状态
|
|
|
mine_size = 40 # 地图方块大小
|
|
|
# 数字0~9的字体颜色rgb
|
|
|
fgs = [(255, 255, 255), (9, 147, 62), (0, 187, 187), (240, 78, 0), (166, 19, 188)
|
|
|
, (185, 122, 87), (136, 0, 21), (163, 73, 164), (0, 0, 0), (0, 0, 0)]
|
|
|
# 方块状态颜色与背景图片
|
|
|
bgs = [(128, 128, 128), (255, 255, 255), (0, 255, 0), (255, 0, 0), (255, 200, 0), (0, 255, 0), (163, 73, 164)]
|
|
|
images = ['area.png', 'opened.png', 'flag.png', 'doubt.png', 'boom.png', 'sweeped.png', 'mistake.png']
|
|
|
pic = []
|
|
|
|
|
|
# 创建地图
|
|
|
def create_map(w=w, h=h, mine=mine, x0=x0, y0=x0,
|
|
|
mine_size=mine_size, fgs=fgs, bgs=bgs, images=images):
|
|
|
Sweep.w = w
|
|
|
Sweep.h = h
|
|
|
Sweep.mine = mine
|
|
|
Sweep.x0 = x0
|
|
|
Sweep.y0 = y0
|
|
|
Sweep.mine_size = mine_size
|
|
|
Sweep.fgs = fgs
|
|
|
Sweep.bgs = bgs
|
|
|
Sweep.images = images
|
|
|
Sweep.state = 0
|
|
|
Sweep.count = 0
|
|
|
|
|
|
# 加载背景图片
|
|
|
if not Sweep.pic:
|
|
|
for filename in Sweep.images:
|
|
|
image = get_image(filename, Sweep.mine_size, Sweep.mine_size)
|
|
|
Sweep.pic.append(image)
|
|
|
|
|
|
def init_map(root):
|
|
|
|
|
|
size_str = '{}x{}+400+80'.format(Sweep.w * Sweep.mine_size + 80, Sweep.h * Sweep.mine_size + 100)
|
|
|
root.geometry(size_str)
|
|
|
|
|
|
Sweep.state = 0
|
|
|
Sweep.count = 0
|
|
|
|
|
|
for button in Sweep.map:
|
|
|
button.destroy()
|
|
|
Sweep.map.clear()
|
|
|
root.update()
|
|
|
|
|
|
random_numbers = random.sample(range(0, Sweep.w * Sweep.h), Sweep.mine)
|
|
|
|
|
|
for i in range(Sweep.w * Sweep.h):
|
|
|
r = i // Sweep.w
|
|
|
c = i % Sweep.w
|
|
|
n = 9 if i in random_numbers else 0
|
|
|
button = Sweep(root)
|
|
|
button.place(x=c * Sweep.mine_size + Sweep.x0, y=r * Sweep.mine_size + Sweep.y0
|
|
|
, width=Sweep.mine_size, height=Sweep.mine_size)
|
|
|
button.setPos(r=r, c=c, n=n)
|
|
|
|
|
|
for mine in Sweep.map:
|
|
|
mine.map_mine()
|
|
|
|
|
|
root.update()
|
|
|
Sweep.reset_map()
|
|
|
|
|
|
def reset_map():
|
|
|
|
|
|
Sweep.state = 0
|
|
|
for mine in Sweep.map:
|
|
|
mine.state = 0
|
|
|
mine.update_style()
|
|
|
|
|
|
def __init__(self, master=None, cnf={}, **kw):
|
|
|
|
|
|
super().__init__(master, cnf, **kw)
|
|
|
|
|
|
self.text = self['text']
|
|
|
self.command = self['command']
|
|
|
self.bind('<Button-1>', self.clicked)
|
|
|
self.bind('<Button-3>', self.right_clicked)
|
|
|
self.r = 0
|
|
|
self.c = 0
|
|
|
self.n = 0
|
|
|
self.state = 0 # 0没有被打开 1已经被打开 2被标志 3被质疑 4打开是雷被爆炸 5被扫除 6标志错误
|
|
|
|
|
|
self.update_style()
|
|
|
self.__class__.map.append(self)
|
|
|
|
|
|
|
|
|
|
|
|
def clicked(self, event):
|
|
|
|
|
|
if self.__class__.state != 0:
|
|
|
# tkinter.messagebox.showinfo(title="游戏结束!",message = "游戏已经结束,请重新开始")
|
|
|
return
|
|
|
if self.state == 1: return
|
|
|
|
|
|
if self.n == 9:
|
|
|
self.gameover()
|
|
|
return
|
|
|
|
|
|
if self.n == 0:
|
|
|
self.auto_sweep()
|
|
|
self.vectory()
|
|
|
return
|
|
|
|
|
|
self.__class__.count += 1
|
|
|
self.state = 1
|
|
|
self.update_style()
|
|
|
|
|
|
self.vectory()
|
|
|
|
|
|
def right_clicked(self, event):
|
|
|
|
|
|
if self.state == 1: return
|
|
|
if self.state == 0:
|
|
|
self.state = 2
|
|
|
elif self.state == 2:
|
|
|
self.state = 3
|
|
|
elif self.state == 3:
|
|
|
self.state = 0
|
|
|
self.update_style()
|
|
|
|
|
|
def setPos(self, r, c, n):
|
|
|
self.r = r
|
|
|
self.c = c
|
|
|
self.n = n
|
|
|
|
|
|
def map_mine(self):
|
|
|
|
|
|
if self.n != 9:
|
|
|
return
|
|
|
|
|
|
neighbors = [(self.r + i, self.c + j) for i in range(-1, 2) for j in range(-1, 2) if i != 0 or j != 0]
|
|
|
for r, c in neighbors:
|
|
|
for mine in self.__class__.map:
|
|
|
if mine.r == r and mine.c == c and mine.n != 9:
|
|
|
mine.n += 1
|
|
|
|
|
|
def update_style(self):
|
|
|
|
|
|
text = str("")
|
|
|
if self.n != 0 and self.n != 9 and self.state == 1: text = str(self.n)
|
|
|
|
|
|
hex_fg = '#{:02x}{:02x}{:02x}'.format(self.__class__.fgs[self.n][0]
|
|
|
, self.__class__.fgs[self.n][1],
|
|
|
self.__class__.fgs[self.n][2])
|
|
|
|
|
|
hex_bg = '#{:02x}{:02x}{:02x}'.format(self.__class__.bgs[self.state][0]
|
|
|
, self.__class__.bgs[self.state][1],
|
|
|
self.__class__.bgs[self.state][2])
|
|
|
|
|
|
image = self.__class__.pic[self.state]
|
|
|
self.image = image
|
|
|
|
|
|
if self.state == 2:
|
|
|
text = str("!")
|
|
|
hex_fg = "red"
|
|
|
elif self.state == 3:
|
|
|
text = str("?")
|
|
|
hex_fg = str("yellow")
|
|
|
elif self.state == 6:
|
|
|
text = str("×")
|
|
|
hex_fg = str("red")
|
|
|
|
|
|
if image != None:
|
|
|
hex_bg = None
|
|
|
|
|
|
self.configure(bg=hex_bg, fg=hex_fg, image=image, text=text, compound=tkinter.CENTER)
|
|
|
|
|
|
def auto_sweep(self):
|
|
|
|
|
|
if self.state == 1: return
|
|
|
|
|
|
self.state = 1
|
|
|
self.update_style()
|
|
|
self.__class__.count += 1
|
|
|
|
|
|
if self.n != 0:
|
|
|
return
|
|
|
|
|
|
neighbors = [(self.r + i, self.c + j) for i in range(-1, 2) for j in range(-1, 2) if i != 0 or j != 0]
|
|
|
for r, c in neighbors:
|
|
|
for mine in self.__class__.map:
|
|
|
if mine.r == r and mine.c == c and mine.n != 9:
|
|
|
mine.clicked(None)
|
|
|
|
|
|
def gameover(self):
|
|
|
|
|
|
self.state = 4
|
|
|
self.__class__.state = 2
|
|
|
|
|
|
for mine in self.__class__.map:
|
|
|
if mine.n == 9 and mine.state != 2:
|
|
|
mine.state = 4
|
|
|
mine.update_style()
|
|
|
elif mine.n != 9 and mine.state == 2:
|
|
|
mine.state = 6
|
|
|
mine.update_style()
|
|
|
img_gif = tkinter.PhotoImage(file='monkeyble.gif')
|
|
|
label_img = tkinter.Label(root, image=img_gif)
|
|
|
label_img.pack()
|
|
|
tkinter.messagebox.showinfo(parent=self, title="游戏结束!", message="失败!")
|
|
|
|
|
|
def vectory(self):
|
|
|
if self.__class__.count == (self.__class__.h * self.__class__.w - self.__class__.mine):
|
|
|
if self.__class__.state != 1:
|
|
|
img_gif = tkinter.PhotoImage(file='monkeyle.gif')
|
|
|
label_img = tkinter.Label(root, image=img_gif)
|
|
|
label_img.pack()
|
|
|
tkinter.messagebox.showinfo("游戏结束!", "恭喜过关!!!")
|
|
|
self.__class__.state = 1
|
|
|
|
|
|
|
|
|
root = tkinter.Tk()
|
|
|
|
|
|
|
|
|
def del_menu(args):
|
|
|
if args == "入门":
|
|
|
Sweep.create_map(w=6, h=5, mine=1)
|
|
|
elif args == "简单":
|
|
|
Sweep.create_map(w=10, h=10, mine=15)
|
|
|
elif args == "一般":
|
|
|
Sweep.create_map(w=16, h=16, mine=40)
|
|
|
elif args == "困难":
|
|
|
Sweep.create_map(w=20, h=16, mine=60)
|
|
|
elif args == "重新开始":
|
|
|
pass
|
|
|
Sweep.init_map(root)
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
root.title('扫雷')
|
|
|
root.iconbitmap('monkey.ico')
|
|
|
Sweep.create_map(w=6, h=5, mine=3)
|
|
|
Sweep.init_map(root)
|
|
|
|
|
|
menu_bar = tkinter.Menu(root)
|
|
|
root.config(menu=menu_bar)
|
|
|
|
|
|
game_menu = tkinter.Menu(menu_bar, tearoff=False)
|
|
|
menu_bar.add_cascade(label="游戏设置", menu=game_menu)
|
|
|
|
|
|
game_menu.add_command(label="入门", command=lambda: del_menu("入门"))
|
|
|
game_menu.add_command(label="简单", command=lambda: del_menu("简单"))
|
|
|
game_menu.add_command(label="一般", command=lambda: del_menu("一般"))
|
|
|
game_menu.add_command(label="困难", command=lambda: del_menu("困难"))
|
|
|
game_menu.add_command(label="重新开始", command=lambda: del_menu("重新开始"))
|
|
|
|
|
|
# root.iconbitmap('mine.ico')
|
|
|
root.mainloop()
|