关灯游戏及扩展


7.8    图形界面应用案例——关灯游戏

题目:

[案例]游戏初步——关灯游戏。    

关灯游戏是很有意思的益智游戏,玩家通过单击关掉(或打开)一盏灯。如果关(掉(或打开)一个电灯,其周围(上下左右)的电灯也会触及开关,成功地关掉所有电灯即可过关。


图7-43 关灯游戏运行效果
分析:游戏中采用二维列表存储灯的状态,'you'表示电灯亮(黄色的圆),'wu'表示电灯关掉(背景色的圆)。在Canvas画布单击事件中,获取鼠标单击位置从而换算成棋盘位(x1,y1),并处理四周灯的状态转换。
案例代码:

from tkinter import *
from tkinter import messagebox
root = Tk()
l= [['wu', 'wu', 'you', 'you', 'you'] ,['wu', 'you', 'wu', 'wu', 'wu'],['wu', 'wu', 'wu', 'wu', 'wu'],['wu', 'wu', 'wu', 'you', 'wu'],['you', 'you', 'you', 'wu', 'wu']]
#绘制灯的状态情况图
def huaqi():for i in range (0,5):for u in range (0,5):if l[i][u]=='you':cv.create_oval(i * 40 + 10,u * 40 + 10,(i+1)* 40+10,(u+1)*40 + 10,outline='white', fill='yellow', width=2)#亮灯else:cv.create_oval(i*40 + 10,u*40 +10,(i+1) *40+10,(u+1)*40 + 10,outline='white', fill='white', width=2)	#灭灯
#反转(x1,yl)处灯的状态
def reserve(x1,y1):if l[x1][y1] =='wu':l[x1][y1]='you'else:l[x1][y1] = 'wu'
#单击事件函数
def luozi(event):x1 = (event.x - 10) // 40y1 = (event.y - 10) // 40print(x1, y1)reserve(x1, y1)  # 翻转(x1,y1)处灯的状态# 以下翻转(x1,yI)周围的灯的状态#左侧灯的状态反转if x1 !=0:reserve(x1 - 1, y1)# 右侧灯的状态反转if x1!=4:reserve(x1 + 1, y1)# 上侧灯的状态反转if y1!=0:reserve(x1, y1 - 1)# 下侧灯的状态反转if y1!=4:reserve(x1, y1 + 1)huaqi()
# 主程序
cv = Canvas(root, bg='white', width=210, height=210)
for i in range(0, 6):  # 绘制网格线cv.create_line(10, 10 + 1 * 40,210, 10 + i * 40, arrow = 'none')cv.create_line(10 + i * 40,10,10 + 1 * 40, 210, arrow = 'none' )
huaqi()  # 绘制灯的状态情况图
p = 0
for i in range(0, 5):for u in l[i]:if u == 'wu':p= p + 1
if p == 25:messagebox.showinfo('win', '你过关了')  # 显示赢信息的消息窗口
cv.bind('<Button-1>', luozi)
cv.pack()
root.mainloop ()

这段代码是一个基于Tkinter库的灯泡游戏。游戏界面是一个5x5的网格,每个网格代表一个灯泡。初始状态下,所有的灯泡都是灭的(白色)。玩家的目标是通过点击灯泡,将所有的灯泡都点亮(黄色)。

代码中的主要函数和操作包括:

1. `huaqi()`函数:根据灯泡的状态情况,绘制灯泡的图形。如果灯泡是亮的,则绘制一个黄色的圆形;如果灯泡是灭的,则绘制一个白色的圆形。

2. `reserve(x1, y1)`函数:根据给定的坐标`(x1, y1)`,反转该位置的灯泡的状态。如果灯泡是亮的,则变为灭的;如果灯泡是灭的,则变为亮的。

3. `luozi(event)`函数:处理鼠标点击事件。根据点击的位置,确定对应的灯泡,并进行状态反转。同时,还会反转该灯泡周围的灯泡状态。

4. 主程序部分:创建一个画布(Canvas)对象,并设置背景色为白色。然后,使用循环绘制网格线。接着,调用`huaqi()`函数绘制灯泡的初始状态。最后,绑定鼠标左键点击事件到`luozi()`函数,并将画布显示在窗口中。

在游戏过程中,玩家通过点击灯泡来改变它的状态,并且反转周围灯泡的状态。当所有的灯泡都点亮时,会弹出一个消息窗口显示玩家胜利的信息。

注(Tkinter库):

Tkinter是Python的标准图形用户界面(GUI)工具包,它提供了创建和管理GUI应用程序所需的组件和功能。Tkinter是基于Tcl/Tk工具包的Python接口,Tcl是一种脚本语言,而Tk是一个用于创建图形用户界面的工具包。

Tkinter库包含了许多常用的GUI组件,比如按钮、标签、文本框、复选框、单选按钮、菜单等,同时也支持布局管理器来帮助开发者设计和布局界面。开发者可以使用Tkinter来创建各种类型的应用程序,从简单的工具到复杂的桌面应用程序都可以使用Tkinter来实现。

Tkinter的优点包括:

1. **易于学习和使用**:Tkinter是Python的标准库,因此无需额外安装即可使用。它的接口简单直观,适合初学者入门。

2. **跨平台性**:Tkinter可以在多个平台上运行,包括Windows、Linux和Mac OS等。

3. **丰富的组件**:Tkinter提供了丰富的GUI组件,可以满足大部分应用程序的需求。

4. **灵活性**:Tkinter支持自定义组件和样式,开发者可以根据自己的需求进行定制。

总之,Tkinter是一个功能强大且易于使用的GUI工具包,适合用于开发Python图形界面应用程序。

扩展题目:

题目要求:

请完成《7.8关灯游戏》(课本p.170),并完成以下扩展内容:

扩展内容:

1. 请设计并实现界面功能,允许玩家选择初始地图的大小,分别为:小(5x5),中(8x8),大(12x10),玩家选择之后立即刷新窗口界面并重设地图

2. 请设计并实现界面功能,允许玩家选择游戏难度,分别为:

容易:一开始有20%的格子状态为翻转状态

中等:一开始有40%的格子状态为翻转状态

困难:一开始有60%的格子状态为翻转状态

3. 游戏开始之前,提示玩家输入唯一的用户名,用于保留该玩家的闯关记录

4. 按照玩家选择的地图大小和难度开始游戏,游戏过程中记录玩家闯关的总时间以及翻转次数(即开关灯的次数)

5. 玩家通关成功后,保存相关信息到数据库,表结构可以自定,但应当至少包含以下信息:

 - 玩家选择的地图大小

 - 玩家选择的难度

 - 玩家通关的日期时间

 - 玩家通关所用的总时间

 - 玩家通关所用的总点击次数

6. 设计窗口界面,显示通关排行榜,具体说明如下:

 - 根据不同地图大小以及不同难度显示各自排名,例如:大地图中等难度与中地图困难难度的排名是分开的

 - 可以选择显示总排名(所有玩家的记录)与个人排名(玩家自己的所有记录)

 - 可以选择根据通关时间排名,以及根据点击次数排名,两个排名都是按从小到大排列

扩展完第一个功能的代码

(1. 请设计并实现界面功能,允许玩家选择初始地图的大小,分别为:小(5x5),中(8x8),大(12x10),玩家选择之后立即刷新窗口界面并重设地图):

from tkinter import *
from tkinter import messagebox
import randomclass LightsOutGame:def __init__(self, master=None, size=5):self.master = masterself.size = sizeself.lights = [['wu' for _ in range(size)] for _ in range(size)]self.create_widgets()self.random_open_lights()  # 随机打开一些灯def create_widgets(self):self.cv = Canvas(self.master, bg='white', width=self.size*40+10, height=self.size*40+10)self.cv.pack()self.draw_grid()  # 绘制网格self.huaqi()  # 绘制灯的状态情况图self.cv.bind('<Button-1>', self.luozi)def draw_grid(self):self.cv.delete("grid")  # 清除之前的网格for i in range(self.size+1):  # 绘制网格线self.cv.create_line(10, 10 + i * 40, 10 + self.size * 40, 10 + i * 40, arrow='none', tags="grid")self.cv.create_line(10 + i * 40, 10, 10 + i * 40, 10 + self.size * 40, arrow='none', tags="grid")def huaqi(self):self.cv.delete("lights")  # 清除之前的灯for i in range(self.size):for u in range(self.size):if self.lights[i][u] == 'you':self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='yellow', width=2, tags="lights")  # 亮灯else:self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='white', width=2, tags="lights")  # 灭灯def reserve(self, x1, y1):if self.lights[x1][y1] == 'wu':self.lights[x1][y1] = 'you'else:self.lights[x1][y1] = 'wu'def luozi(self, event):x1 = (event.x - 10) // 40y1 = (event.y - 10) // 40print(x1, y1)self.reserve(x1, y1)  # 翻转(x1,y1)处灯的状态# 以下翻转(x1,yI)周围的灯的状态#左侧灯的状态反转if x1 != 0:self.reserve(x1 - 1, y1)# 右侧灯的状态反转if x1 != self.size - 1:self.reserve(x1 + 1, y1)# 上侧灯的状态反转if y1 != 0:self.reserve(x1, y1 - 1)# 下侧灯的状态反转if y1 != self.size - 1:self.reserve(x1, y1 + 1)self.huaqi()def random_open_lights(self):num_of_lights = random.randint(1, self.size*self.size)  # 随机选择要打开的灯的数量positions = random.sample(range(self.size*self.size), num_of_lights)  # 随机选择要打开的灯的位置for pos in positions:x = pos // self.sizey = pos % self.sizeself.reserve(x, y)def reset_game(size):game.size = sizegame.lights = [['wu' for _ in range(size)] for _ in range(size)]game.cv.config(width=size*40+10, height=size*40+10)game.draw_grid()game.random_open_lights()game.huaqi()def on_small():reset_game(5)def on_medium():reset_game(8)def on_large():reset_game(12)root = Tk()
game = LightsOutGame(root)menu_frame = Frame(root)
menu_frame.pack()small_button = Button(menu_frame, text="小", command=on_small)
small_button.pack(side=LEFT)medium_button = Button(menu_frame, text="中", command=on_medium)
medium_button.pack(side=LEFT)large_button = Button(menu_frame, text="大", command=on_large)
large_button.pack(side=LEFT)root.mainloop()

扩展完功能二的代码:

请设计并实现界面功能,允许玩家选择游戏难度,分别为:

容易:一开始有20%的格子状态为翻转状态

中等:一开始有40%的格子状态为翻转状态

困难:一开始有60%的格子状态为翻转状态

from tkinter import *
from tkinter import messagebox
import randomclass LightsOutGame:def __init__(self, master=None, size=5, difficulty='medium'):self.master = masterself.size = sizeself.lights = [['wu' for _ in range(size)] for _ in range(size)]self.create_widgets()self.random_open_lights(difficulty)  # 随机打开一些灯def create_widgets(self):self.cv = Canvas(self.master, bg='white', width=self.size*40+10, height=self.size*40+10)self.cv.pack()self.draw_grid()  # 绘制网格self.huaqi()  # 绘制灯的状态情况图self.cv.bind('<Button-1>', self.luozi)def draw_grid(self):self.cv.delete("grid")  # 清除之前的网格for i in range(self.size+1):  # 绘制网格线self.cv.create_line(10, 10 + i * 40, 10 + self.size * 40, 10 + i * 40, arrow='none', tags="grid")self.cv.create_line(10 + i * 40, 10, 10 + i * 40, 10 + self.size * 40, arrow='none', tags="grid")def huaqi(self):self.cv.delete("lights")  # 清除之前的灯for i in range(self.size):for u in range(self.size):if self.lights[i][u] == 'you':self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='yellow', width=2, tags="lights")  # 亮灯else:self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='white', width=2, tags="lights")  # 灭灯def reserve(self, x1, y1):if self.lights[x1][y1] == 'wu':self.lights[x1][y1] = 'you'else:self.lights[x1][y1] = 'wu'def luozi(self, event):x1 = (event.x - 10) // 40y1 = (event.y - 10) // 40print(x1, y1)self.reserve(x1, y1)  # 翻转(x1,y1)处灯的状态# 以下翻转(x1,yI)周围的灯的状态#左侧灯的状态反转if x1 != 0:self.reserve(x1 - 1, y1)# 右侧灯的状态反转if x1 != self.size - 1:self.reserve(x1 + 1, y1)# 上侧灯的状态反转if y1 != 0:self.reserve(x1, y1 - 1)# 下侧灯的状态反转if y1 != self.size - 1:self.reserve(x1, y1 + 1)self.huaqi()def random_open_lights(self, difficulty):if difficulty == 'easy':num_of_lights = int(self.size * self.size * 0.2)  # 20%的格子状态为翻转状态elif difficulty == 'medium':num_of_lights = int(self.size * self.size * 0.4)  # 40%的格子状态为翻转状态elif difficulty == 'hard':num_of_lights = int(self.size * self.size * 0.6)  # 60%的格子状态为翻转状态positions = random.sample(range(self.size*self.size), num_of_lights)  # 随机选择要打开的灯的位置for pos in positions:x = pos // self.sizey = pos % self.sizeself.reserve(x, y)def reset_game(size, difficulty):game.size = sizegame.lights = [['wu' for _ in range(size)] for _ in range(size)]game.cv.config(width=size*40+10, height=size*40+10)game.draw_grid()game.random_open_lights(difficulty)game.huaqi()def on_small():reset_game(5, difficulty_var.get())def on_medium():reset_game(8, difficulty_var.get())def on_large():reset_game(12, difficulty_var.get())root = Tk()
game = LightsOutGame(root)menu_frame = Frame(root)
menu_frame.pack()difficulty_var = StringVar()
difficulty_var.set('medium')small_button = Button(menu_frame, text="小", command=on_small)
small_button.pack(side=LEFT)medium_button = Button(menu_frame, text="中", command=on_medium)
medium_button.pack(side=LEFT)large_button = Button(menu_frame, text="大", command=on_large)
large_button.pack(side=LEFT)difficulty_frame = Frame(root)
difficulty_frame.pack()easy_radio = Radiobutton(difficulty_frame, text="容易", variable=difficulty_var, value='easy')
easy_radio.pack(side=LEFT)medium_radio = Radiobutton(difficulty_frame, text="中等", variable=difficulty_var, value='medium')
medium_radio.pack(side=LEFT)hard_radio = Radiobutton(difficulty_frame, text="困难", variable=difficulty_var, value='hard')
hard_radio.pack(side=LEFT)root.mainloop()

扩展完功能三的代码:

3. 游戏开始之前,提示玩家输入唯一的用户名,用于保留该玩家的闯关记录

from tkinter import *
from tkinter import messagebox
import randomclass LightsOutGame:def __init__(self, master=None, size=5, difficulty='medium'):self.master = masterself.size = sizeself.lights = [['wu' for _ in range(size)] for _ in range(size)]self.username = None  # 存储玩家的用户名self.create_widgets()self.random_open_lights(difficulty)  # 随机打开一些灯def create_widgets(self):self.cv = Canvas(self.master, bg='white', width=self.size*40+10, height=self.size*40+10)self.cv.pack()self.draw_grid()  # 绘制网格self.huaqi()  # 绘制灯的状态情况图self.cv.bind('<Button-1>', self.luozi)self.username_label = Label(self.master, text="用户名:")self.username_label.pack()self.username_entry = Entry(self.master)self.username_entry.pack()self.username_button = Button(self.master, text="确认", command=self.set_username)self.username_button.pack()def set_username(self):self.username = self.username_entry.get()self.username_label.config(text="用户名:" + self.username)# 移除用户名输入框和确认按钮self.username_entry.pack_forget()self.username_button.pack_forget()def draw_grid(self):self.cv.delete("grid")  # 清除之前的网格for i in range(self.size+1):  # 绘制网格线self.cv.create_line(10, 10 + i * 40, 10 + self.size * 40, 10 + i * 40, arrow='none', tags="grid")self.cv.create_line(10 + i * 40, 10, 10 + i * 40, 10 + self.size * 40, arrow='none', tags="grid")def huaqi(self):self.cv.delete("lights")  # 清除之前的灯for i in range(self.size):for u in range(self.size):if self.lights[i][u] == 'you':self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='yellow', width=2, tags="lights")  # 亮灯else:self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='white', width=2, tags="lights")  # 灭灯def reserve(self, x1, y1):if self.lights[x1][y1] == 'wu':self.lights[x1][y1] = 'you'else:self.lights[x1][y1] = 'wu'def luozi(self, event):x1 = (event.x - 10) // 40y1 = (event.y - 10) // 40print(x1, y1)self.reserve(x1, y1)  # 翻转(x1,y1)处灯的状态# 以下翻转(x1,yI)周围的灯的状态#左侧灯的状态反转if x1 != 0:self.reserve(x1 - 1, y1)# 右侧灯的状态反转if x1 != self.size - 1:self.reserve(x1 + 1, y1)# 上侧灯的状态反转if y1 != 0:self.reserve(x1, y1 - 1)# 下侧灯的状态反转if y1 != self.size - 1:self.reserve(x1, y1 + 1)self.huaqi()def random_open_lights(self, difficulty):if difficulty == 'easy':num_of_lights = int(self.size * self.size * 0.2)  # 20%的格子状态为翻转状态elif difficulty == 'medium':num_of_lights = int(self.size * self.size * 0.4)  # 40%的格子状态为翻转状态elif difficulty == 'hard':num_of_lights = int(self.size * self.size * 0.6)  # 60%的格子状态为翻转状态positions = random.sample(range(self.size*self.size), num_of_lights)  # 随机选择要打开的灯的位置for pos in positions:x = pos // self.sizey = pos % self.sizeself.reserve(x, y)def reset_game(size, difficulty, username):game.username = usernamegame.size = sizegame.lights = [['wu' for _ in range(size)] for _ in range(size)]game.cv.config(width=size*40+10, height=size*40+10)game.draw_grid()game.random_open_lights(difficulty)game.huaqi()def on_small():reset_game(5, difficulty_var.get(), game.username)def on_medium():reset_game(8, difficulty_var.get(), game.username)def on_large():reset_game(12, difficulty_var.get(), game.username)root = Tk()
game = LightsOutGame(root)menu_frame = Frame(root)
menu_frame.pack()difficulty_var = StringVar()
difficulty_var.set('medium')small_button = Button(menu_frame, text="小", command=on_small)
small_button.pack(side=LEFT)medium_button = Button(menu_frame, text="中", command=on_medium)
medium_button.pack(side=LEFT)large_button = Button(menu_frame, text="大", command=on_large)
large_button.pack(side=LEFT)difficulty_frame = Frame(root)
difficulty_frame.pack()easy_radio = Radiobutton(difficulty_frame, text="容易", variable=difficulty_var, value='easy')
easy_radio.pack(side=LEFT)medium_radio = Radiobutton(difficulty_frame, text="中等", variable=difficulty_var, value='medium')
medium_radio.pack(side=LEFT)hard_radio = Radiobutton(difficulty_frame, text="困难", variable=difficulty_var, value='hard')
hard_radio.pack(side=LEFT)root.mainloop()

扩展完功能四的代码:

按照玩家选择的地图大小和难度开始游戏,游戏过程中记录玩家闯关的总时间以及翻转次数(即开关灯的次数)

from tkinter import *
from tkinter import messagebox
import random
import timeclass LightsOutGame:def __init__(self, master=None, size=5, difficulty='medium'):self.master = masterself.size = sizeself.lights = [['wu' for _ in range(size)] for _ in range(size)]self.username = None  # 存储玩家的用户名self.create_widgets()self.random_open_lights(difficulty)  # 随机打开一些灯self.total_time = 0self.flip_count = 0self.start_time = 0def create_widgets(self):self.cv = Canvas(self.master, bg='white', width=self.size*40+10, height=self.size*40+10)self.cv.pack()self.draw_grid()  # 绘制网格self.huaqi()  # 绘制灯的状态情况图self.cv.bind('<Button-1>', self.luozi)self.username_label = Label(self.master, text="用户名:")self.username_label.pack()self.username_entry = Entry(self.master)self.username_entry.pack()self.username_button = Button(self.master, text="确认", command=self.set_username)self.username_button.pack()def set_username(self):self.username = self.username_entry.get()self.username_label.config(text="用户名:" + self.username)# 移除用户名输入框和确认按钮self.username_entry.pack_forget()self.username_button.pack_forget()def draw_grid(self):self.cv.delete("grid")  # 清除之前的网格for i in range(self.size+1):  # 绘制网格线self.cv.create_line(10, 10 + i * 40, 10 + self.size * 40, 10 + i * 40, arrow='none', tags="grid")self.cv.create_line(10 + i * 40, 10, 10 + i * 40, 10 + self.size * 40, arrow='none', tags="grid")def huaqi(self):self.cv.delete("lights")  # 清除之前的灯for i in range(self.size):for u in range(self.size):if self.lights[i][u] == 'you':self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='yellow', width=2, tags="lights")  # 亮灯else:self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='white', width=2, tags="lights")  # 灭灯def reserve(self, x1, y1):if self.lights[x1][y1] == 'wu':self.lights[x1][y1] = 'you'else:self.lights[x1][y1] = 'wu'def luozi(self, event):x1 = (event.x - 10) // 40y1 = (event.y - 10) // 40print(x1, y1)self.reserve(x1, y1)  # 翻转(x1,y1)处灯的状态# 以下翻转(x1,yI)周围的灯的状态#左侧灯的状态反转if x1 != 0:self.reserve(x1 - 1, y1)# 右侧灯的状态反转if x1 != self.size - 1:self.reserve(x1 + 1, y1)# 上侧灯的状态反转if y1 != 0:self.reserve(x1, y1 - 1)# 下侧灯的状态反转if y1 != self.size - 1:self.reserve(x1, y1 + 1)self.huaqi()self.flip_count += 1def random_open_lights(self, difficulty):if difficulty == 'easy':num_of_lights = int(self.size * self.size * 0.2)  # 20%的格子状态为翻转状态elif difficulty == 'medium':num_of_lights = int(self.size * self.size * 0.4)  # 40%的格子状态为翻转状态elif difficulty == 'hard':num_of_lights = int(self.size * self.size * 0.6)  # 60%的格子状态为翻转状态positions = random.sample(range(self.size*self.size), num_of_lights)  # 随机选择要打开的灯的位置for pos in positions:x = pos // self.sizey = pos % self.sizeself.reserve(x, y)def reset_game(size, difficulty, username):game.username = usernamegame.size = sizegame.lights = [['wu' for _ in range(size)] for _ in range(size)]game.cv.config(width=size*40+10, height=size*40+10)game.draw_grid()game.random_open_lights(difficulty)game.huaqi()game.total_time = 0game.flip_count = 0game.start_time = 0def on_small():reset_game(5, difficulty_var.get(), game.username)def on_medium():reset_game(8, difficulty_var.get(), game.username)def on_large():reset_game(12, difficulty_var.get(), game.username)root = Tk()
game = LightsOutGame(root)menu_frame = Frame(root)
menu_frame.pack()difficulty_var = StringVar()
difficulty_var.set('medium')small_button = Button(menu_frame, text="小", command=on_small)
small_button.pack(side=LEFT)medium_button = Button(menu_frame, text="中", command=on_medium)
medium_button.pack(side=LEFT)large_button = Button(menu_frame, text="大", command=on_large)
large_button.pack(side=LEFT)difficulty_frame = Frame(root)
difficulty_frame.pack()easy_radio = Radiobutton(difficulty_frame, text="容易", variable=difficulty_var, value='easy')
easy_radio.pack(side=LEFT)medium_radio = Radiobutton(difficulty_frame, text="中等", variable=difficulty_var, value='medium')
medium_radio.pack(side=LEFT)hard_radio = Radiobutton(difficulty_frame, text="困难", variable=difficulty_var, value='hard')
hard_radio.pack(side=LEFT)root.mainloop()

扩展完功能五的代码:

 玩家通关成功后,保存相关信息到数据库,表结构可以自定,但应当至少包含以下信息:

 - 玩家选择的地图大小

 - 玩家选择的难度

 - 玩家通关的日期时间

 - 玩家通关所用的总时间

 - 玩家通关所用的总点击次数

import sqlite3
from tkinter import *
from tkinter import messagebox
import random
from datetime import datetimeclass LightsOutGame:def __init__(self, master=None, size=5, difficulty='medium'):self.master = masterself.size = sizeself.lights = [['wu' for _ in range(size)] for _ in range(size)]self.username = None  # 存储玩家的用户名self.create_widgets()self.random_open_lights(difficulty)  # 随机打开一些灯self.total_time = 0self.flip_count = 0self.start_time = 0# 连接到数据库self.conn = sqlite3.connect('game.db')self.cursor = self.conn.cursor()# 创建表self.cursor.execute('''CREATE TABLE IF NOT EXISTS game_records (id INTEGER PRIMARY KEY AUTOINCREMENT,map_size INTEGER,difficulty TEXT,completion_time DATETIME,total_clicks INTEGER)''')def create_widgets(self):self.cv = Canvas(self.master, bg='white', width=self.size*40+10, height=self.size*40+10)self.cv.pack()self.draw_grid()  # 绘制网格self.huaqi()  # 绘制灯的状态情况图self.cv.bind('<Button-1>', self.luozi)self.username_label = Label(self.master, text="用户名:")self.username_label.pack()self.username_entry = Entry(self.master)self.username_entry.pack()self.username_button = Button(self.master, text="确认", command=self.set_username)self.username_button.pack()def set_username(self):self.username = self.username_entry.get()self.username_label.config(text="用户名:" + self.username)# 移除用户名输入框和确认按钮self.username_entry.pack_forget()self.username_button.pack_forget()def draw_grid(self):self.cv.delete("grid")  # 清除之前的网格for i in range(self.size+1):  # 绘制网格线self.cv.create_line(10, 10 + i * 40, 10 + self.size * 40, 10 + i * 40, arrow='none', tags="grid")self.cv.create_line(10 + i * 40, 10, 10 + i * 40, 10 + self.size * 40, arrow='none', tags="grid")def huaqi(self):self.cv.delete("lights")  # 清除之前的灯for i in range(self.size):for u in range(self.size):if self.lights[i][u] == 'you':self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='yellow', width=2, tags="lights")  # 亮灯else:self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='white', width=2, tags="lights")  # 灭灯def reserve(self, x1, y1):if self.lights[x1][y1] == 'wu':self.lights[x1][y1] = 'you'else:self.lights[x1][y1] = 'wu'def luozi(self, event):x1 = (event.x - 10) // 40y1 = (event.y - 10) // 40print(x1, y1)self.reserve(x1, y1)  # 翻转(x1,y1)处灯的状态# 以下翻转(x1,yI)周围的灯的状态#左侧灯的状态反转if x1 != 0:self.reserve(x1 - 1, y1)# 右侧灯的状态反转if x1 != self.size - 1:self.reserve(x1 + 1, y1)# 上侧灯的状态反转if y1 != 0:self.reserve(x1, y1 - 1)# 下侧灯的状态反转if y1 != self.size - 1:self.reserve(x1, y1 + 1)self.huaqi()self.flip_count += 1def random_open_lights(self, difficulty):if difficulty == 'easy':num_of_lights = int(self.size * self.size * 0.2)  # 20%的格子状态为翻转状态elif difficulty == 'medium':num_of_lights = int(self.size * self.size * 0.4)  # 40%的格子状态为翻转状态elif difficulty == 'hard':num_of_lights = int(self.size * self.size * 0.6)  # 60%的格子状态为翻转状态positions = random.sample(range(self.size*self.size), num_of_lights)  # 随机选择要打开的灯的位置for pos in positions:x = pos // self.sizey = pos % self.sizeself.reserve(x, y)def save_game_record(self):# 保存通关信息到数据库map_size = self.sizedifficulty = difficulty_var.get()completion_time = datetime.now()total_clicks = self.flip_countself.cursor.execute('''INSERT INTO game_records (map_size, difficulty, completion_time, total_clicks)VALUES (?, ?, ?, ?)''', (map_size, difficulty, completion_time, total_clicks))self.conn.commit()def reset_game(size, difficulty, username):game.username = usernamegame.size = sizegame.lights = [['wu' for _ in range(size)] for _ in range(size)]game.cv.config(width=size*40+10, height=size*40+10)game.draw_grid()game.random_open_lights(difficulty)game.huaqi()game.total_time = 0game.flip_count = 0game.start_time = 0def on_small():reset_game(5, difficulty_var.get(), game.username)def on_medium():reset_game(8, difficulty_var.get(), game.username)def on_large():reset_game(12, difficulty_var.get(), game.username)root = Tk()
game = LightsOutGame(root)menu_frame = Frame(root)
menu_frame.pack()difficulty_var = StringVar()
difficulty_var.set('medium')small_button = Button(menu_frame, text="小", command=on_small)
small_button.pack(side=LEFT)medium_button = Button(menu_frame, text="中", command=on_medium)
medium_button.pack(side=LEFT)large_button = Button(menu_frame, text="大", command=on_large)
large_button.pack(side=LEFT)difficulty_frame = Frame(root)
difficulty_frame.pack()easy_radio = Radiobutton(difficulty_frame, text="容易", variable=difficulty_var, value='easy')
easy_radio.pack(side=LEFT)medium_radio = Radiobutton(difficulty_frame, text="中等", variable=difficulty_var, value='medium')
medium_radio.pack(side=LEFT)hard_radio = Radiobutton(difficulty_frame, text="困难", variable=difficulty_var, value='hard')
hard_radio.pack(side=LEFT)save_button = Button(root, text="保存通关信息", command=game.save_game_record)
save_button.pack()root.mainloop()# 关闭数据库连接
game.conn.close()

扩展完功能六的代码:

设计窗口界面,显示通关排行榜,具体说明如下:

 - 根据不同地图大小以及不同难度显示各自排名,例如:大地图中等难度与中地图困难难度的排名是分开的

 - 可以选择显示总排名(所有玩家的记录)与个人排名(玩家自己的所有记录)

 - 可以选择根据通关时间排名,以及根据点击次数排名,两个排名都是按从小到大排列

import sqlite3
from tkinter import *
from tkinter import messagebox
import random
from datetime import datetimeclass LightsOutGame:def __init__(self, master=None, size=5, difficulty='medium'):self.master = masterself.size = sizeself.lights = [['wu' for _ in range(size)] for _ in range(size)]self.username = None  # 存储玩家的用户名self.create_widgets()self.random_open_lights(difficulty)  # 随机打开一些灯self.total_time = 0self.flip_count = 0self.start_time = 0# 连接到数据库self.conn = sqlite3.connect('game.db')self.cursor = self.conn.cursor()# 创建表self.cursor.execute('''CREATE TABLE IF NOT EXISTS game_records (id INTEGER PRIMARY KEY AUTOINCREMENT,username TEXT,map_size INTEGER,difficulty TEXT,completion_time DATETIME,total_clicks INTEGER)''')def create_widgets(self):self.cv = Canvas(self.master, bg='white', width=self.size * 40 + 10, height=self.size * 40 + 10)self.cv.pack()self.draw_grid()  # 绘制网格self.huaqi()  # 绘制灯的状态情况图self.cv.bind('<Button-1>', self.luozi)self.username_label = Label(self.master, text="用户名:")self.username_label.pack()self.username_entry = Entry(self.master)self.username_entry.pack()self.username_button = Button(self.master, text="确认", command=self.set_username)self.username_button.pack()self.show_leaderboard_button = Button(self.master, text="显示排行榜", command=self.show_leaderboard)self.show_leaderboard_button.pack()def set_username(self):self.username = self.username_entry.get()self.username_label.config(text="用户名:" + self.username)# 移除用户名输入框和确认按钮self.username_entry.pack_forget()self.username_button.pack_forget()def draw_grid(self):self.cv.delete("grid")  # 清除之前的网格for i in range(self.size + 1):  # 绘制网格线self.cv.create_line(10, 10 + i * 40, 10 + self.size * 40, 10 + i * 40, arrow='none', tags="grid")self.cv.create_line(10 + i * 40, 10, 10 + i * 40, 10 + self.size * 40, arrow='none', tags="grid")def huaqi(self):self.cv.delete("lights")  # 清除之前的灯for i in range(self.size):for u in range(self.size):if self.lights[i][u] == 'you':self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='yellow', width=2, tags="lights")  # 亮灯else:self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='white', width=2, tags="lights")  # 灭灯def reserve(self, x1, y1):if self.lights[x1][y1] == 'wu':self.lights[x1][y1] = 'you'else:self.lights[x1][y1] = 'wu'def luozi(self, event):x1 = (event.x - 10) // 40y1 = (event.y - 10) // 40print(x1, y1)self.reserve(x1, y1)  # 翻转(x1,y1)处灯的状态# 以下翻转(x1,yI)周围的灯的状态#左侧灯的状态反转if x1 != 0:self.reserve(x1 - 1, y1)# 右侧灯的状态反转if x1 != self.size - 1:self.reserve(x1 + 1, y1)# 上侧灯的状态反转if y1 != 0:self.reserve(x1, y1 - 1)# 下侧灯的状态反转if y1 != self.size - 1:self.reserve(x1, y1 + 1)self.huaqi()self.flip_count += 1def random_open_lights(self, difficulty):if difficulty == 'easy':num_of_lights = int(self.size * self.size * 0.2)  # 20%的格子状态为翻转状态elif difficulty == 'medium':num_of_lights = int(self.size * self.size * 0.4)  # 40%的格子状态为翻转状态elif difficulty == 'hard':num_of_lights = int(self.size * self.size * 0.6)  # 60%的格子状态为翻转状态positions = random.sample(range(self.size * self.size), num_of_lights)  # 随机选择要打开的灯的位置for pos in positions:x = pos // self.sizey = pos % self.sizeself.reserve(x, y)def save_game_record(self):# 保存通关信息到数据库map_size = self.sizedifficulty = difficulty_var.get()completion_time = datetime.now()total_clicks = self.flip_countself.cursor.execute('''INSERT INTO game_records (username, map_size, difficulty, completion_time, total_clicks)VALUES (?, ?, ?, ?, ?)''', (self.username, map_size, difficulty, completion_time, total_clicks))self.conn.commit()  # 确保数据被写入数据库def show_leaderboard(self):leaderboard_window = Toplevel(self.master)leaderboard_window.title("通关排行榜")leaderboard_frame = Frame(leaderboard_window)leaderboard_frame.pack()map_size = self.sizedifficulty = difficulty_var.get()self.cursor.execute('''SELECT username, completion_time, total_clicks FROM game_recordsWHERE map_size=? AND difficulty=?ORDER BY completion_time, total_clicks''', (map_size, difficulty))records = self.cursor.fetchall()if len(records) == 0:messagebox.showinfo("提示", "暂无记录")else:for i, record in enumerate(records):username_label = Label(leaderboard_frame, text=record[0])username_label.grid(row=i, column=0)completion_time_label = Label(leaderboard_frame, text=record[1])completion_time_label.grid(row=i, column=1)total_clicks_label = Label(leaderboard_frame, text=record[2])total_clicks_label.grid(row=i, column=2)def reset_game(size, difficulty, username):game.username = usernamegame.size = sizegame.lights = [['wu' for _ in range(size)] for _ in range(size)]game.cv.config(width=size * 40 + 10, height=size * 40 + 10)game.draw_grid()game.random_open_lights(difficulty)game.huaqi()game.total_time = 0game.flip_count = 0game.start_time = 0def on_small():reset_game(5, difficulty_var.get(), game.username)def on_medium():reset_game(8, difficulty_var.get(), game.username)def on_large():reset_game(12, difficulty_var.get(), game.username)root = Tk()
game = LightsOutGame(root)menu_frame = Frame(root)
menu_frame.pack()difficulty_var = StringVar()
difficulty_var.set('medium')small_button = Button(menu_frame, text="小", command=on_small)
small_button.pack(side=LEFT)medium_button = Button(menu_frame, text="中", command=on_medium)
medium_button.pack(side=LEFT)large_button = Button(menu_frame, text="大", command=on_large)
large_button.pack(side=LEFT)difficulty_frame = Frame(root)
difficulty_frame.pack()easy_radio = Radiobutton(difficulty_frame, text="容易", variable=difficulty_var, value='easy')
easy_radio.pack(side=LEFT)medium_radio = Radiobutton(difficulty_frame, text="中等", variable=difficulty_var, value='medium')
medium_radio.pack(side=LEFT)hard_radio = Radiobutton(difficulty_frame, text="困难", variable=difficulty_var, value='hard')
hard_radio.pack(side=LEFT)save_button = Button(root, text="保存通关信息", command=game.save_game_record)
save_button.pack()root.mainloop()# 关闭数据库连接
game.conn.close()

扩展添加了一个查询次数和时间的代码(最终):

import sqlite3
from tkinter import *
from tkinter import messagebox
import random
from datetime import datetimeclass LightsOutGame:def __init__(self, master=None, size=5, difficulty='medium'):self.master = masterself.size = sizeself.lights = [['wu' for _ in range(size)] for _ in range(size)]self.username = None  # 存储玩家的用户名self.create_widgets()self.random_open_lights(difficulty)  # 随机打开一些灯self.total_time = 0self.flip_count = 0self.start_time = 0# 连接到数据库self.conn = sqlite3.connect('game.db')self.cursor = self.conn.cursor()# 创建表self.cursor.execute('''CREATE TABLE IF NOT EXISTS game_records (id INTEGER PRIMARY KEY AUTOINCREMENT,username TEXT,map_size INTEGER,difficulty TEXT,completion_time DATETIME,total_clicks INTEGER)''')def create_widgets(self):self.cv = Canvas(self.master, bg='white', width=self.size * 40 + 10, height=self.size * 40 + 10)self.cv.pack()self.draw_grid()  # 绘制网格self.huaqi()  # 绘制灯的状态情况图self.cv.bind('<Button-1>', self.luozi)self.username_label = Label(self.master, text="用户名:")self.username_label.pack()self.username_entry = Entry(self.master)self.username_entry.pack()self.username_button = Button(self.master, text="确认", command=self.set_username)self.username_button.pack()self.show_leaderboard_button = Button(self.master, text="显示排行榜", command=self.show_leaderboard)self.show_leaderboard_button.pack()self.stats_button = Button(self.master, text="查询统计", command=self.show_game_stats)self.stats_button.pack()self.stats_label = Label(self.master, text="")self.stats_label.pack()def set_username(self):self.username = self.username_entry.get()self.username_label.config(text="用户名:" + self.username)# 移除用户名输入框和确认按钮self.username_entry.pack_forget()self.username_button.pack_forget()def draw_grid(self):self.cv.delete("grid")  # 清除之前的网格for i in range(self.size + 1):  # 绘制网格线self.cv.create_line(10, 10 + i * 40, 10 + self.size * 40, 10 + i * 40, arrow='none', tags="grid")self.cv.create_line(10 + i * 40, 10, 10 + i * 40, 10 + self.size * 40, arrow='none', tags="grid")def huaqi(self):self.cv.delete("lights")  # 清除之前的灯for i in range(self.size):for u in range(self.size):if self.lights[i][u] == 'you':self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='yellow', width=2, tags="lights")  # 亮灯else:self.cv.create_oval(i * 40 + 10, u * 40 + 10, (i + 1) * 40 + 10, (u + 1) * 40 + 10,outline='white', fill='white', width=2, tags="lights")  # 灭灯def reserve(self, x1, y1):if self.lights[x1][y1] == 'wu':self.lights[x1][y1] = 'you'else:self.lights[x1][y1] = 'wu'def luozi(self, event):x1 = (event.x - 10) // 40y1 = (event.y - 10) // 40print(x1, y1)self.reserve(x1, y1)  # 翻转(x1,y1)处灯的状态# 以下翻转(x1,yI)周围的灯的状态#左侧灯的状态反转if x1 != 0:self.reserve(x1 - 1, y1)# 右侧灯的状态反转if x1 != self.size - 1:self.reserve(x1 + 1, y1)# 上侧灯的状态反转if y1 != 0:self.reserve(x1, y1 - 1)# 下侧灯的状态反转if y1 != self.size - 1:self.reserve(x1, y1 + 1)self.huaqi()self.flip_count += 1def random_open_lights(self, difficulty):if difficulty == 'easy':num_of_lights = int(self.size * self.size * 0.2)  # 20%的格子状态为翻转状态elif difficulty == 'medium':num_of_lights = int(self.size * self.size * 0.4)  # 40%的格子状态为翻转状态elif difficulty == 'hard':num_of_lights = int(self.size * self.size * 0.6)  # 60%的格子状态为翻转状态positions = random.sample(range(self.size * self.size), num_of_lights)  # 随机选择要打开的灯的位置for pos in positions:x = pos // self.sizey = pos % self.sizeself.reserve(x, y)def save_game_record(self):# 保存通关信息到数据库map_size = self.sizedifficulty = difficulty_var.get()completion_time = datetime.now()total_clicks = self.flip_countself.cursor.execute('''INSERT INTO game_records (username, map_size, difficulty, completion_time, total_clicks)VALUES (?, ?, ?, ?, ?)''', (self.username, map_size, difficulty, completion_time, total_clicks))self.conn.commit()  # 确保数据被写入数据库def show_leaderboard(self):leaderboard_window = Toplevel(self.master)leaderboard_window.title("通关排行榜")leaderboard_frame = Frame(leaderboard_window)leaderboard_frame.pack()map_size = self.sizedifficulty = difficulty_var.get()self.cursor.execute('''SELECT username, completion_time, total_clicks FROM game_recordsWHERE map_size=? AND difficulty=?ORDER BY completion_time, total_clicks''', (map_size, difficulty))records = self.cursor.fetchall()if len(records) == 0:messagebox.showinfo("提示", "暂无记录")else:for i, record in enumerate(records):username_label = Label(leaderboard_frame, text=record[0])username_label.grid(row=i, column=0)completion_time_label = Label(leaderboard_frame, text=record[1])completion_time_label.grid(row=i, column=1)total_clicks_label = Label(leaderboard_frame, text=record[2])total_clicks_label.grid(row=i, column=2)def get_game_stats(self):self.cursor.execute('''SELECT SUM(completion_time), SUM(total_clicks) FROM game_recordsWHERE username=?''', (self.username,))result = self.cursor.fetchone()return resultdef show_game_stats(self):stats = self.get_game_stats()total_time = stats[0]total_clicks = stats[1]self.stats_label.config(text=f"总时间:{total_time} 秒,翻转次数:{total_clicks} 次")def reset_game(size, difficulty, username):game.username = usernamegame.size = sizegame.lights = [['wu' for _ in range(size)] for _ in range(size)]game.cv.config(width=size * 40 + 10, height=size * 40 + 10)game.draw_grid()game.random_open_lights(difficulty)game.huaqi()game.total_time = 0game.flip_count = 0game.start_time = 0game.stats_label.config(text="")def on_small():reset_game(5, difficulty_var.get(), game.username)def on_medium():reset_game(8, difficulty_var.get(), game.username)def on_large():reset_game(12, difficulty_var.get(), game.username)root = Tk()
game = LightsOutGame(root)menu_frame = Frame(root)
menu_frame.pack()difficulty_var = StringVar()
difficulty_var.set('medium')small_button = Button(menu_frame, text="小", command=on_small)
small_button.pack(side=LEFT)medium_button = Button(menu_frame, text="中", command=on_medium)
medium_button.pack(side=LEFT)large_button = Button(menu_frame, text="大", command=on_large)
large_button.pack(side=LEFT)difficulty_frame = Frame(root)
difficulty_frame.pack()easy_radio = Radiobutton(difficulty_frame, text="容易", variable=difficulty_var, value='easy')
easy_radio.pack(side=LEFT)medium_radio = Radiobutton(difficulty_frame, text="中等", variable=difficulty_var, value='medium')
medium_radio.pack(side=LEFT)hard_radio = Radiobutton(difficulty_frame, text="困难", variable=difficulty_var, value='hard')
hard_radio.pack(side=LEFT)save_button = Button(root, text="保存通关信息", command=game.save_game_record)
save_button.pack()root.mainloop()# 关闭数据库连接
game.conn.close()

相关问题:

  1. 请描述你的系统详细设计(提示:按照需求分析列出概要功能点)

答:系统详细设计:

创建一个名为LightsOutGame的类,用于实现Lights Out游戏的逻辑和界面。

在初始化方法中,设置游戏的大小、难度,并创建一个二维数组来表示灯的状态。

创建游戏界面,包括一个Canvas用于绘制网格和灯的状态,一个Label用于显示用户名,一个Entry和一个Button用于输入和确认用户名,以及一些按钮用于选择游戏难度和操作。

实现灯的状态翻转和绘制网格、灯的方法。

实现随机打开一些灯的方法,根据难度设置打开的灯的数量。

实现保存通关记录到数据库的方法,包括用户名、地图大小、难度、完成时间和翻转次数。

实现显示排行榜和查询统计的方法,从数据库中获取相应的记录并展示在界面上。

实现重置游戏的方法,根据选择的地图大小和难度重新设置游戏参数,并清空灯的状态和统计数据。

创建一个主窗口,并将游戏对象放入其中,启动主循环。

  1. 请通过原型图+说明的方式展示你的界面详细设计

答:

界面详细设计:

主界面包括一个Canvas用于绘制网格和灯的状态,一个Label用于显示用户名,一个Entry和一个Button用于输入和确认用户名,以及一些按钮用于选择游戏难度和操作。

用户名输入框和确认按钮位于顶部,用于输入和确认用户名。

网格和灯的状态绘制在Canvas上,根据灯的状态绘制不同的颜色和形状。

游戏难度选择按钮位于中间,用于选择不同的难度。

排行榜和查询统计按钮位于底部,用于显示排行榜和查询统计信息。

  1. 请通过ER图+表结构说明的方式展示你的数据库详细设计

答:

数据库详细设计:

创建一个名为game_records的表,用于存储通关记录。

表中包含以下字段:id(主键,自增),username(用户名),map_size(地图大小),difficulty(难度),completion_time(完成时间),total_clicks(翻转次数)。

使用SQLite数据库,通过Python的sqlite3模块连接和操作数据库。

在游戏开始时创建表,如果表已存在则不创建。

在保存通关记录时,将相关信息插入到game_records表中。

在显示排行榜和查询统计时,从game_records表中查询相应的记录,并按照完成时间和翻转次数排序。

  1. 请按功能点顺序(1-6)依次展示你的程序运行截图:

答:功能1:

功能2:

功能3:

功能4:

功能5:

功能6:

  1. 请讨论说明图形界面设计(GUI)包括哪些重要组成部分?

答:图形界面设计(GUI)的重要组成部分包括:

窗口:用于承载界面的容器,提供标题栏、边框和关闭按钮等功能。

组件:用于构建界面的可视化元素,如按钮、标签、文本框、下拉框等。

布局管理器:用于控制组件在窗口中的位置和大小,如pack、grid和place等。

事件处理:用于响应用户的操作,如点击按钮、输入文本等,触发相应的事件处理函数。

图形绘制:用于绘制图形元素,如绘制网格、绘制灯的状态等。

2、请讨论说明在本实验中,你应如何使用数据库支撑整个应用程序的正确运行?

答:在本实验中,数据库用于支持整个应用程序的正确运行,具体包括:

创建数据库表game_records用于存储游戏记录。

在游戏通关时,将通关信息插入到game_records表中。

在显示排行榜时,从game_records表中查询对应难度和地图大小的游戏记录,并在界面上显示。

3、其他关于完成本次实验作业中的心得与讨论

答:本次实验是一个简单的游戏的实现,通过使用Tkinter库构建了一个图形界面,并使用SQLite数据库存储游戏记录。通过这个实验,我学习到了如何使用Tkinter库创建图形界面,以及如何使用SQLite数据库进行数据存储和查询。同时,我也了解到了图形界面设计的重要组成部分和数据库的应用场景。这个实验对于我进一步掌握Python编程和图形界面开发有很大的帮助,也提升了我的数据库操作能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/137978.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JSON可视化管理工具JSON Hero

本文软件由网友 zxc 推荐&#xff1b; 什么是 JSON Hero &#xff1f; JSON Hero 是一个简单实用的 JSON 工具&#xff0c;通过简介美观的 UI 及增强的额外功能&#xff0c;使得阅读和理解 JSON 文档变得更容易、直观。 主要功能 支持多种视图以便查看 JSON&#xff1a;列视图…

css:clip元素裁剪实现Loading加载效果边框

clip 属性定义了元素的哪一部分是可见的。clip 属性只适用于 position:absolute 的元素。 警告&#xff1a; 这个属性已被废弃。建议使用 clip-path 文档 https://developer.mozilla.org/zh-CN/docs/Web/CSS/cliphttps://developer.mozilla.org/zh-CN/docs/Web/CSS/clip-path …

liunx系统目录结构

列出目录 ls -l bin 二进制文件 boot 启动liunx的一些核心文件 dev 外部设备liunx的 etc 存放系统管理的配置文件和子目录都在这里面 home 家目录 lib 动态链接库 windows中的dll lostfound 一般为空 非法关机 存放文件 media 自带识别设备 识别挂载…

Linux安装MySQL8.0服务

Linux安装MySQL8.0服务 文章目录 Linux安装MySQL8.0服务一、卸载1.1 查看mariadb1.2 卸载 二、安装2.1 下载2.2 上传2.3 解压2.4 重命名2.5 删除2.6 创建目录2.7 环境变量2.8 修改配置2.9 配置文件2.9 用户与用户组2.10 初始化2.11 其它 三、开启远程连接MySQL 一、卸载 首先第…

安卓常见设计模式10------责任链模式(Kotlin版)

1. W1 是什么&#xff0c;什么是责任链模式&#xff1f;​ 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;它用于将请求的发送者和接收者解耦&#xff0c;并将请求沿着一个处理链进行传递&#xff0c;直到有一个处理者能…

Hive 知识点八股文记录 ——(二)优化

函数 UDF&#xff1a;用户定义函数 UDAF&#xff1a;用户定义聚集函数 UDTF&#xff1a;用户定义表生成函数 建表优化 分区建桶 创建表时指定分区字段 PARTITIONED BY (date string)指定分桶字段和数量 CLUSTERED BY (id) INTO 10 BUCKETS插入数据按分区、分桶字段插入 …

【数据结构】树与二叉树(八):二叉树的中序遍历(非递归算法NIO)

文章目录 5.2.1 二叉树二叉树性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点&#xff0c;其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…

【postgresql】CentOS7 安装pgAdmin 4

CentOS7 安装PostgreSQL Web管理工具pgAdmin 4。 pgAdmin 是世界上最先进的开源数据库 PostgreSQL 最受欢迎且功能丰富的开源管理和开发平台。 下载地址&#xff1a; pgadmin-4 download pgAdmin 4分为桌面版和服务器版。 我们这里部署服务器版本。 安装RPM包。 安装源 s…

现在学编程还能够月薪过万吗?

当我们谈到职业选择时&#xff0c;一项常受人关注的问题是&#xff0c;现在学编程还能月薪过万吗&#xff1f;这似乎是一个不断挂在年轻人嘴边的问题&#xff0c;尤其是在数字化时代&#xff0c;编程的需求越来越大。 所以今天让我们一起探讨这个问题&#xff0c;看看现实生活…

聊聊logback的ShutdownHook

序 本文主要研究一下logback的ShutdownHook ShutdownHook ch/qos/logback/core/hook/ShutdownHook.java /*** Interface describing a logback shutdown hook implementation* * author Mike Reinhold*/ public interface ShutdownHook extends Runnable, ContextAware { }…

汽车标定技术(九)--标定常量与#pragma的趣事

目录 1. 不添加#pragma语句 2. 添加#pragma语句 3. 标定量只给flash空间&#xff0c;不给ram指定空间 4. 总结 在之前不会使用overlay机制的时候&#xff0c;我们想要做汽车标定&#xff0c;标定常量编译出来的地址一般都应该是ram的地址&#xff0c;而且在链接文件中都会指…

6.5对称二叉树(LC101-E)

算法&#xff1a; 其实就是比较左右子树是否可以翻转 比较的时候&#xff1a; 比较外面的节点是否相等&#xff0c;如示例1中的节点3 比较里面的节点是否相等&#xff0c;如示例1中的节点4 基本思路是这样的&#xff0c;那怎么遍历呢&#xff1f; 二叉树的题一定要掌握到…

更安全的ssh协议与Gui图形化界面使用

目录 前言&#xff1a; 一.Gui图形化界面的使用 二.ssh协议 SSH的主要作用包括&#xff1a; 相比其他网络协议&#xff0c;SSH的优势包括&#xff1a; 三.idea集成Git 前言&#xff1a; 上一篇讲解了git的命令用法以及https协议&#xff0c;但是这个协议放在做团队项目的…

Git系列之Git集成开发工具及git扩展使用

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《Git实战开发》。&#x1f3af;&#x1f3af; &a…

我的月光宝盒初体验失败了

哈哈哈&#xff0c;我爱docker, docker 使我自由&#xff01;&#xff01;&#xff01; docker make me free! 菠萝菠萝蜜口号喊起来。 https://github.com/vivo/MoonBox/ windows上安装好了docker之后&#xff0c;docker-compose是自带的。 docker-compose -f docker-compo…

Springboot整合Jedis实现单机版或哨兵版可切换配置

Springboot整合Jedis实现单机版或哨兵版可切换配置 前言实现最后 前言 前文写到借助redis实现Shiro实现session限制登录数量踢人下线&#xff0c;本文就写一下Jedis的配置&#xff0c;可切换单机版和集群哨兵版&#xff0c;方便开发测试。 实现 很简单&#xff0c;直接上代码&…

王学岗visibility改变后调用onLayout()

自定义控件的时候发现了一个bug。 Button位移动画执行结束后我设置了一个不相关的TextView的可见性由gone变为visible.令人郁闷的是&#xff0c;只要我注释的地方放开。动画执行结束后button都会重新绘制在位移动画开始的位置。注释掉这段代码就正常。 经过分析后得知 View的Vi…

C# OpenCvSharp DNN HybridNets 同时处理车辆检测、可驾驶区域分割、车道线分割

效果 项目 代码 using OpenCvSharp; using OpenCvSharp.Dnn; using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Numerics; using System.Text; using System.Windows.Forms;namespace OpenCvSharp_D…

城市内涝积水的原因有哪些?万宾科技内涝积水监测仪工作原理

一旦有暴雨预警出现多地便会立即响应&#xff0c;以防城市内涝问题出现。随着人口迁移&#xff0c;越来越多的人口涌入城市之中&#xff0c;为了完善城市基础设施建设&#xff0c;城市应急管理部门对内涝的监测越来越严格&#xff0c;在信息化时代&#xff0c;城市管理也趋向于…

G2406C是一款高效的直流-直流降压开关稳压器,能够提供高达1A输出电流。

G2406C 1.5MHz&#xff0c;1A高效降压DC-DC转换器 概述: G2406C是一款高效的直流-直流降压开关稳压器&#xff0c;能够提供高达1A输出电流。G2406C在2.7V至5.5V的宽范围输入电压下工作&#xff0c;使IC是低压电源转换的理想选择。在1.5MHz的固定频率下运行允许使用具有小电感…