运行效果图
mport wx
from random import randint
class MineFrame(wx.Frame):
def __init__(self):
# 设置窗口为固定大小
wx.Frame.__init__(self,None,-1,'扫雷',size=(515,503),
style=wx.SYSTEM_MENU | wx.MINIMIZE_BOX | wx.CLOSE_BOX | wx.CAPTION)
self.time_count = 0 # 初始化计时为0
self.mine_last = 100 # 初始化雷数为100
self.get_mine_set()# 获取雷的索引集合
self.get_info_set()# 获取提示信息(索引和雷数)集合
self.del_index_set = set() # 存储被删除的按钮索引
self.get_bmp_list() # 获取位图对象列表
self.SetIcon(wx.Icon(self.bmp_list[9]))# 设置标题图标
self.create_menu() # 生成菜单栏
self.create_panel()# 生成画板
self.create_timer()# 生成计时器
self.create_text_info()# 生成提示信息(雷数和时间)
self.create_state_btn()# 生成状态按钮
self.create_btn_list()# 生成所有按钮
# 菜单栏事件
def e_menu_new(self, e):
pass
def e_menu_level1(self, e):
pass
def e_menu_level2(self, e):
pass
def e_menu_level3(self, e):
pass
def e_menu_custom(self, e):
pass
def e_menu_mark(self, e):
pass
def e_menu_color(self, e):
pass
def e_menu_sound(self, e):
pass
def e_menu_list(self, e):
pass
def e_menu_exit(self, e):
pass
def e_menu_catalogue(self, e):
pass
def e_menu_search(self, e):
pass
def e_menu_help(self, e):
pass
def e_menu_about(self, e):
pass
def create_menu(self):
menu_bar = wx.MenuBar()# 创建菜单栏
# 游戏菜单
gm_menu = wx.Menu()# 创建一个菜单对象
new = gm_menu.Append(-1,"开局(N)\tF2")# 将子菜单加入到菜单对象中
gm_menu.AppendSeparator() # 插入一条分割线
level1 = gm_menu.Append(-1,"初级(B)")
level2 = gm_menu.Append(-1,"中级(I)")
level3 = gm_menu.Append(-1,"高级(E)")
custom = gm_menu.Append(-1, "自定义(C)...")
gm_menu.AppendSeparator()# 插入一条分割线
mark = gm_menu.Append(-1,"标记(?)(M)")
color = gm_menu.Append(-1,"颜色(L)")
sound = gm_menu.Append(-1,"声音(S)")
gm_menu.AppendSeparator()
rs_list = gm_menu.Append(-1, "扫雷英雄榜(T)...")
exit_gm = gm_menu.Append(-1, "退出(X)")
menu_bar.Append(gm_menu,"游戏(&G)")# 将File菜单添加到菜单栏
# 帮助菜单
self.help_menu = wx.Menu()
catalogue = self.help_menu.Append(2,"目录(C)\tF1")
self.help_menu.AppendSeparator()
search_help = self.help_menu.Append(3,"查找帮助主题(S)...")
use_help = self.help_menu.Append(4,"使用帮助(H)")
self.help_menu.AppendSeparator()
about = self.help_menu.Append(9,"关于扫雷(A)...")
menu_bar.Append(self.help_menu,"&帮助(H)")
#设置菜单条
self.SetMenuBar(menu_bar)
# 绑定菜单事件
self.Bind(wx.EVT_MENU, self.e_menu_new, new)
self.Bind(wx.EVT_MENU, self.e_menu_level1, level1)
self.Bind(wx.EVT_MENU, self.e_menu_level2, level2)
self.Bind(wx.EVT_MENU, self.e_menu_level3, level3)
self.Bind(wx.EVT_MENU, self.e_menu_custom, custom)
self.Bind(wx.EVT_MENU, self.e_menu_mark, mark)
self.Bind(wx.EVT_MENU, self.e_menu_color, color)
self.Bind(wx.EVT_MENU, self.e_menu_sound, sound)
self.Bind(wx.EVT_MENU, self.e_menu_list, rs_list)
self.Bind(wx.EVT_MENU, self.e_menu_exit, exit_gm)
self.Bind(wx.EVT_MENU, self.e_menu_catalogue, catalogue)
self.Bind(wx.EVT_MENU, self.e_menu_search, search_help)
self.Bind(wx.EVT_MENU, self.e_menu_help, use_help)
self.Bind(wx.EVT_MENU, self.e_menu_about, about)
def create_panel(self):
self.panel = wx.Panel(self)
self.panel.Bind(wx.EVT_PAINT, self.e_paint)
def get_mine_set(self):
self.mine_set = set()
while(len(self.mine_set)<100):
self.mine_set.add(randint(0,719))
def get_info_set(self):
self.info_set = set()
info_set = set()
for i in self.mine_set:
info_set.update({i-31,i-30,i-29,i-1,i+1,i+29,i+30,i+31})
for i in info_set:
if i not in self.mine_set and i in range(0,720):
count = 0
for j in [i-31,i-30,i-29,i-1,i+1,i+29,i+30,i+31]:
if j in self.mine_set:
count += 1
self.info_set.add((i,count))
def get_bmp_list(self):
image_list = ['smile.png', 'oh.png', 'cry.png', 'com.png', 'flag.png', 'ques.png',
'mine.png', 'emine.png', 'redmine.png','icon.png']
self.bmp_list = [wx.Image(i, wx.BITMAP_TYPE_PNG).ConvertToBitmap() for i in image_list]
def create_state_btn(self):
self.state_btn = wx.BitmapButton(self.panel, -1, self.bmp_list[0], (240, 10), (25, 25))
self.state_btn.Bind(wx.EVT_BUTTON, self.e_restart)
def create_text_info(self):
self.mine_text = wx.StaticText(self.panel, -1, '100', (25, 10))
self.mine_text.SetFont(wx.Font(20, wx.DEFAULT, wx.FONTSTYLE_NORMAL, wx.NORMAL, faceName="黑体"))
self.mine_text.SetForegroundColour(wx.RED)
self.time_text = wx.StaticText(self.panel, -1, '000', (440, 10))
self.time_text.SetFont(wx.Font(20, wx.DEFAULT, wx.FONTSTYLE_NORMAL, wx.NORMAL, faceName="黑体"))
self.time_text.SetForegroundColour(wx.RED)
def create_timer(self):
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.e_time, self.timer)
def draw_panel(self):
self.dc = wx.ClientDC(self.panel)
self.dc.SetBrush(wx.Brush(wx.Colour(192, 192, 192))) # 设置填充颜色
self.dc.SetPen(wx.GREY_PEN) # 设置线条颜色
self.dc.DrawRectangle(9, 50, 480, 384) # 画方框
for i in range(1, 24):
self.dc.DrawLine(9, 16 * i + 50, 480 + 9, 16 * i + 50) # 画横线
for i in range(1, 30):
self.dc.DrawLine(16 * i + 9, 50, 16 * i + 9, 384 + 50) # 画竖线
for i in self.mine_set:
self.dc.DrawBitmap(self.bmp_list[6],i % 30 * 16 + 10, i // 30 * 16 + 1 + 50)# 画地雷
text_color_dict = {1: '#0000ff', 2: '#008000', 3: '#ff0000', 4: '#000080', 5: '#800000',
6: '#e4007f', 7: '#6a3906', 8: '#000000'} # 数量和颜色字典
for i in self.info_set:
self.dc.SetTextForeground(text_color_dict[i[1]]) # 查找相应的颜色
self.dc.DrawText(str(i[1]), i[0] % 30 * 16 + 5 + 9, i[0] // 30 * 16 + 1 + 50) # 显示雷数
def create_btn_list(self):
self.btn_list = []
index = 0
for i in range(0, 24):
for j in range(0, 30):
btn = wx.BitmapButton(self.panel,-1,self.bmp_list[3],(j * 16+9, i * 16+50),(17, 17))
btn.index = index
btn.state = 0
self.btn_list.append(btn)
index += 1
for i in self.btn_list:
i.Bind(wx.EVT_LEFT_DOWN,self.e_left_down)
i.Bind(wx.EVT_LEFT_UP,self.e_left_up)
i.Bind(wx.EVT_RIGHT_DOWN,self.e_right_down)
def stop_game(self,index):
self.state_btn.SetBitmap(self.bmp_list[2])
self.timer.Stop()
error_marked_set = set()
for i, j in enumerate(self.btn_list):
if i not in self.del_index_set:
if i in self.mine_set:
if j.state != 1:
j.Destroy()
self.del_index_set.add(i)
else:
if j.state == 1:
j.Destroy()
self.del_index_set.add(i)
error_marked_set.add(i)
if i not in self.del_index_set:
j.Unbind(wx.EVT_LEFT_UP, handler=self.e_left_up) # 剩余的按钮解绑所有事件
j.Unbind(wx.EVT_LEFT_DOWN, handler=self.e_left_down)
j.Unbind(wx.EVT_RIGHT_DOWN, handler=self.e_right_down)
self.panel.Unbind(wx.EVT_PAINT, handler=self.e_paint) # 解绑绘图事件
self.draw_panel() # 重新生成面板
self.dc.DrawBitmap(self.bmp_list[8],index % 30 * 16 + 10, index // 30 * 16 + 1 + 50)# 画红色炸雷
self.dc.SetBrush(wx.TRANSPARENT_BRUSH)
self.dc.DrawRectangle(index % 30 * 16 + 9, index // 30 * 16 + 50, 16, 16)
for i in error_marked_set:
self.dc.DrawBitmap(self.bmp_list[7], i % 30 * 16 + 10, i // 30 * 16 + 1 + 50) # 画地雷
def del_btn(self,btn,index):
self.state_btn.SetBitmap(self.bmp_list[0])
if index not in self.del_index_set and btn.state != 1:
if index in [i[0] for i in self.info_set]:
btn.Destroy()
self.del_index_set.add(index)
else:
if index not in self.mine_set:
btn.Destroy()
self.del_index_set.add(index)
for j in [index - 31, index - 30, index - 29, index - 1, index + 1, index + 29, index + 30,
index + 31]:
if j in range(0, 720) and j not in self.mine_set \
and j not in self.del_index_set \
and self.btn_list[j].state != 1:
self.btn_list[j].Destroy()
self.del_index_set.add(j)
def e_paint(self,e):
self.draw_panel()
def e_time(self,e):
self.time_count += 1
self.time_text.SetLabel('%03d'%self.time_count)
def e_left_up(self,e):
if not self.timer.IsRunning():
self.timer.Start(1000)
btn = e.GetEventObject()
index = btn.index
if btn.state == 1:
self.state_btn.SetBitmap(self.bmp_list[0])
else:
if index in self.mine_set:
self.stop_game(index)
else:
self.del_btn(btn,index)
def e_left_down(self,e):
self.state_btn.SetBitmap(self.bmp_list[1])
def e_right_down(self,e):
btn = e.GetEventObject()
index = btn.index
label = btn.state
if label == 0:
btn.SetBitmap(self.bmp_list[4])
btn.state = 1
self.mine_last -= 1
self.mine_text.SetLabel('%03d' %self.mine_last)
elif label == 1:
btn.SetBitmap(self.bmp_list[5])
btn.state = 2
self.mine_last += 1
self.mine_text.SetLabel('%03d' % self.mine_last)
else:
btn.SetBitmap(self.bmp_list[3])
btn.state = 0
def e_restart(self,e):
# 结束
if self.timer.IsRunning():
self.timer.Stop()# 计时器清零
for i,j in enumerate(self.btn_list):
if i not in self.del_index_set:
j.Destroy()# 删掉所有按钮
# 重启
self.get_mine_set()
self.get_info_set()
self.panel.Bind(wx.EVT_PAINT, self.e_paint)
self.time_count = 0
self.mine_last = 100
self.del_index_set = set()
self.state_btn.SetBitmap(self.bmp_list[0])
self.mine_text.SetLabel('100')
self.time_text.SetLabel('000')
self.create_btn_list()
if __name__=='__main__':
app = wx.App()
frame = MineFrame()
frame.Show()
app.MainLoop()