关灯游戏及扩展

news2024/10/6 14:37:13


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) // 40
    y1 = (event.y - 10) // 40
    print(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 random

class LightsOutGame:
    def __init__(self, master=None, size=5):
        self.master = master
        self.size = size
        self.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) // 40
        y1 = (event.y - 10) // 40
        print(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.size
            y = pos % self.size
            self.reserve(x, y)

def reset_game(size):
    game.size = size
    game.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 random

class LightsOutGame:
    def __init__(self, master=None, size=5, difficulty='medium'):
        self.master = master
        self.size = size
        self.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) // 40
        y1 = (event.y - 10) // 40
        print(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.size
            y = pos % self.size
            self.reserve(x, y)

def reset_game(size, difficulty):
    game.size = size
    game.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 random

class LightsOutGame:
    def __init__(self, master=None, size=5, difficulty='medium'):
        self.master = master
        self.size = size
        self.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) // 40
        y1 = (event.y - 10) // 40
        print(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.size
            y = pos % self.size
            self.reserve(x, y)

def reset_game(size, difficulty, username):
    game.username = username
    game.size = size
    game.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 time

class LightsOutGame:
    def __init__(self, master=None, size=5, difficulty='medium'):
        self.master = master
        self.size = size
        self.lights = [['wu' for _ in range(size)] for _ in range(size)]
        self.username = None  # 存储玩家的用户名
        self.create_widgets()
        self.random_open_lights(difficulty)  # 随机打开一些灯
        self.total_time = 0
        self.flip_count = 0
        self.start_time = 0

    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) // 40
        y1 = (event.y - 10) // 40
        print(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 += 1

    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.size
            y = pos % self.size
            self.reserve(x, y)

def reset_game(size, difficulty, username):
    game.username = username
    game.size = size
    game.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 = 0
    game.flip_count = 0
    game.start_time = 0

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()

扩展完功能五的代码:

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

 - 玩家选择的地图大小

 - 玩家选择的难度

 - 玩家通关的日期时间

 - 玩家通关所用的总时间

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

import sqlite3
from tkinter import *
from tkinter import messagebox
import random
from datetime import datetime

class LightsOutGame:
    def __init__(self, master=None, size=5, difficulty='medium'):
        self.master = master
        self.size = size
        self.lights = [['wu' for _ in range(size)] for _ in range(size)]
        self.username = None  # 存储玩家的用户名
        self.create_widgets()
        self.random_open_lights(difficulty)  # 随机打开一些灯
        self.total_time = 0
        self.flip_count = 0
        self.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) // 40
        y1 = (event.y - 10) // 40
        print(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 += 1

    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.size
            y = pos % self.size
            self.reserve(x, y)

    def save_game_record(self):
        # 保存通关信息到数据库
        map_size = self.size
        difficulty = difficulty_var.get()
        completion_time = datetime.now()
        total_clicks = self.flip_count

        self.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 = username
    game.size = size
    game.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 = 0
    game.flip_count = 0
    game.start_time = 0

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()

扩展完功能六的代码:

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

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

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

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

import sqlite3
from tkinter import *
from tkinter import messagebox
import random
from datetime import datetime

class LightsOutGame:
    def __init__(self, master=None, size=5, difficulty='medium'):
        self.master = master
        self.size = size
        self.lights = [['wu' for _ in range(size)] for _ in range(size)]
        self.username = None  # 存储玩家的用户名
        self.create_widgets()
        self.random_open_lights(difficulty)  # 随机打开一些灯
        self.total_time = 0
        self.flip_count = 0
        self.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) // 40
        y1 = (event.y - 10) // 40
        print(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 += 1

    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.size
            y = pos % self.size
            self.reserve(x, y)

    def save_game_record(self):
        # 保存通关信息到数据库
        map_size = self.size
        difficulty = difficulty_var.get()
        completion_time = datetime.now()
        total_clicks = self.flip_count

        self.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.size
        difficulty = difficulty_var.get()

        self.cursor.execute('''SELECT username, completion_time, total_clicks FROM game_records
                                WHERE 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 = username
    game.size = size
    game.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 = 0
    game.flip_count = 0
    game.start_time = 0

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()

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

import sqlite3
from tkinter import *
from tkinter import messagebox
import random
from datetime import datetime

class LightsOutGame:
    def __init__(self, master=None, size=5, difficulty='medium'):
        self.master = master
        self.size = size
        self.lights = [['wu' for _ in range(size)] for _ in range(size)]
        self.username = None  # 存储玩家的用户名
        self.create_widgets()
        self.random_open_lights(difficulty)  # 随机打开一些灯
        self.total_time = 0
        self.flip_count = 0
        self.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) // 40
        y1 = (event.y - 10) // 40
        print(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 += 1

    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.size
            y = pos % self.size
            self.reserve(x, y)

    def save_game_record(self):
        # 保存通关信息到数据库
        map_size = self.size
        difficulty = difficulty_var.get()
        completion_time = datetime.now()
        total_clicks = self.flip_count

        self.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.size
        difficulty = difficulty_var.get()

        self.cursor.execute('''SELECT username, completion_time, total_clicks FROM game_records
                                WHERE 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_records
                                WHERE username=?''', (self.username,))
        result = self.cursor.fetchone()
        return result

    def 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 = username
    game.size = size
    game.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 = 0
    game.flip_count = 0
    game.start_time = 0
    game.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.coloradmin.cn/o/1193352.html

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

相关文章

Hadoop架构、Hive相关知识点及Hive执行流程

Hadoop架构 Hadoop由三大部分组成:HDFS、MapReduce、yarn HDFS&#xff1a;负责数据的存储 其中包括&#xff1a; namenode&#xff1a;主节点&#xff0c;用来分配任务给从节点 secondarynamenode&#xff1a;副节点&#xff0c;辅助主节点 datanode&#xff1a;从节点&#x…

Linux编写一个极简版本的Shell

Linux编写一个极简版本的Shell &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容在Linux环境下&#xff…

二十五、W5100S/W5500+RP2040树莓派Pico<Modebus TCP Server示例>

文章目录 1 前言2 简介2 .1 什么是Modbus TCP&#xff1f;2.2 Modbus TCP指令介绍2.3 请求数据过程2.4 Modbus TCP协议优点2.5 Modbus TCP应用场景 3 WIZnet以太网芯片4 Modbus TCP示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意…

nacos做服务配置和服务器发现

一、创建项目 1、创建一个spring-boot的项目 2、创建三个模块file、system、gateway模块 3、file和system分别配置启动信息,并且创建一个简单的控制器 server.port9000 spring.application.namefile server.servlet.context-path/file4、在根目录下引入依赖 <properties&g…

Maven-依赖管理机制

一、背景和起源 依赖管理是Maven的一个核心功能。管理单个模块项目的依赖相对比较容易&#xff0c;但是如果是多模块项目或者有几百个模块的项目就是一个巨大的挑战。 如果手动构建项目&#xff0c;那么就先需要梳理各个模块pom中定义的依赖和版本&#xff0c;然后进行下载到本…

C++模拟实现set和map

1.看源码&#xff0c;简单了解原码的set和map类的结构 1.看类的私有成员和类模板的参数&#xff1a; 看下面我画的一些框&#xff0c;再结合上面的看一下&#xff0c;会有什么疑惑呢&#xff1f; 一般我们知道编译器底层的代码会很简洁&#xff0c;不会多创建无意义的内容&am…

【使用教程】在Ubuntu下PMM60系列一体化伺服电机通过PDO跑循环同步位置模式详解

本教程将指导您在Ubuntu操作系统下使用PDO来配置和控制PMM60系列一体化伺服电机以实现循环同步位置模式。我们将介绍必要的步骤和命令&#xff0c;以确保您能够成功地配置和控制PMM系列一体化伺服电机。 一、准备工作 在正式介绍之前还需要一些准备工作&#xff1a;1.装有lin…

环保壁炉:酒精壁炉的生态优势

环保已经成为一个备受重视的话题。我们都希望采用更环保的能源&#xff0c;以减少对地球的影响。而酒精壁炉作为一种新型的取暖方式&#xff0c;正受到越来越多人的喜爱&#xff0c;因为它们代表了一种清洁能源的选择。 酒精壁炉的独特之处在于它们使用酒精作为燃料。这种酒精…

NFT数字藏品(交易平台)系统开发

随着数字技术和区块链技术的发展&#xff0c;NFT数字藏品交易平台系统开发逐渐成为了一个热门话题。NFT&#xff0c;即非同质化代币&#xff0c;可以用来代表独一无二的数字资产&#xff0c;如图片、音频、视频等&#xff0c;在数字世界中具有极高的价值。本文将介绍NFT数字藏品…

11.10论文写作与格式

格式 文章题目&#xff1a;&#xff08;三号、黑体、加粗&#xff0c;居中&#xff09; 摘要&#xff1a;这两个大字要&#xff08;黑体、小四、加粗&#xff0c;左对齐&#xff09;&#xff1b;内容为(宋体、小四) 关键词&#xff1a;三个字为(黑体、小四、加粗&#xff0c…

动作捕捉系统通过SDK与LabVIEW通信

运动分析、VR、机器人等应用中常使用LabVIEW对动作捕捉数据进行实时解算。NOKOV度量动作捕捉系统支持通过SDK与LabVIEW进行通信&#xff0c;将动作数据传入LabVIEW。 一、软件设置 1、形影软件设置 1、将模式切换到后处理模式 2、加载一个刚体数据 3、打开软件设置 4、选择网…

NFT Insider112:Gucci Cosmos LAND亮相 The Sandbox,和YGG一起探索Web3增长新方式

引言&#xff1a;NFT Insider由NFT收藏组织WHALE Members(https://twitter.com/WHALEMembers)、BeepCrypto&#xff08;https://twitter.com/beep_crypto&#xff09;联合出品&#xff0c;浓缩每周NFT新闻&#xff0c;为大家带来关于NFT最全面、最新鲜、最有价值的讯息。每期周…

实现智慧工地的高效建筑管理,数据分析起着关键作用!

智慧工地是利用物联网、云计算、大数据等技术&#xff0c;实现对建筑工地实时监测、管理和控制的一种新型建筑管理方式。 智慧工地架构&#xff1a; 1、终端层&#xff1a;充分利用物联网技术、移动应用、智能硬件设备提高现场管控能力。通过RFID、传感器、摄像头、手机等终端…

KiB、MiB与KB、MB的区别

KiB、MiB与KB、MB的区别

vue3 + antd 图片上传 (精简篇)cv即可

使用antd组件库里的 a-upload 上传图片 template代码&#xff1a; <a-upload name"idCardzm" list-type"picture-card" class"avatar-uploader" :show-upload-list"false":before-upload"beforeUpload" :customRequest…

喜报!华为云金融PaaS3.0荣获“2023年应用现代化典型案例”称号

中国软件行业协会近期启动了2023“应用现代化产业实践”优秀案例征集活动&#xff0c;旨在加快推动应用现代化发展与推广应用&#xff0c;形成行业应用带动和示范作用&#xff0c;打造应用现代化软件名企、名品&#xff0c;凝聚行业资源&#xff0c;助力我国行业应用现代化高质…

mac使用VMware Fusion安装Centos 7系统

mac主机芯片&#xff1a;Apple M2 Pro VMware-Fusion&#xff1a;13.5 centos&#xff1a;7 第一次操作&#xff1a; 按步骤选择操作系统 在选择虚拟启动虚拟机没有安装centos的界面 而是下图 改动&#xff1a;把UEFI换成BIOS ——>无果 第二次操作&#xff1a; 直接…

国际阿里云:无法ping通ECS实例公网IP的排查方法!!!

无法ping通ECS实例的原因较多&#xff0c;您可以参考本文进行排查。 问题现象 本地客户端无法ping通目标ECS实例公网IP&#xff0c;例如&#xff1a; 本地客户端为Linux系统&#xff0c;ping目标ECS实例公网IP时无响应&#xff0c;如下所示&#xff1a; 本地客户端为Windo…

实时疫情地图及全国监测动态大屏可视化【可视化项目案例-02】

🎉🎊🎉 你的技术旅程将在这里启航! 🚀🚀 本文选自专栏:可视化技术专栏100例 可视化技术专栏100例,包括但不限于大屏可视化、图表可视化等等。订阅专栏用户在文章底部可下载对应案例源码以供大家深入的学习研究。 🎓 每一个案例都会提供完整代码和详细的讲解,不…

【poi导出excel模板——通过建造者模式+策略模式+函数式接口实现】

poi导出excel模板——通过建造者模式策略模式函数式接口实现 poi导出excel示例优化思路代码实现补充建造者模式策略模式 poi导出excel示例 首先我们现看一下poi如何导出excel&#xff0c;这里举个例子&#xff1a;目前想要导出一个Map<sex,List>信息&#xff0c;sex作为…