图形界面应用案例——关灯游戏(以及扩展)(python)


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)处灯的状态

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring中的循环依赖解决方案

前言&#xff1a;测试环境突发BeanCurrentlyInCreationException&#xff0c;导致后端服务启动失败&#xff0c;一看就是Spring的Bean管理中循环依赖。项目中存在Bean的循环依赖&#xff0c;是代码质量低下的表现。多数人寄希望于框架层来给擦屁股&#xff0c;造成了整个代码的…

相机内外参实践之点云投影矢量图

目录 概述 涉及到的坐标变换 深度值可视化 3D点云的2D投影实现 实现效果 参考文献 概述 Camer的内外参在多模态融合中主要涉及到坐标系变换&#xff0c;即像素坐标、相机坐标以及其他坐标系。这篇就针对点云到图像的投影与反投影做代码实践&#xff0c;来构建一张具有深度…

MYSQL 慢查询和慢查询日志

在数据库管理中&#xff0c;慢查询是指执行时间较长的 SQL 查询语句。这类查询可能导致系统性能下降&#xff0c;影响用户体验。为了帮助识别和解决这些性能问题&#xff0c;数据库管理系统通常提供了慢查询日志&#xff0c;用于记录执行时间超过一定阈值的查询。本文将深入探讨…

【pytorch深度学习】使用张量表征真实数据

使用张量表征真实数据 本文为书pytorch深度学习实战的一些学习笔记和扩展知识&#xff0c;涉及到的csv文件等在这里不会给出&#xff0c;但是我会尽量脱离这一些文件将书本想要表达的内容给展示出来。 文章目录 使用张量表征真实数据1. 加载图像文件2. 改变布局3. 加载目录下…

[工业自动化-12]:西门子S7-15xxx编程 - PLC从站 - ET200 SP系列详解

目录 一、概述 1.1 概述 二、系统组成 2.1 概述 2.2 与主站的通信接口模块 2.3 总线适配器 2.4 基座单元 2.5 电子模块 2.6 服务器模块 一、概述 1.1 概述 PLC ET200 SP 是西门子&#xff08;Siemens&#xff09;公司生产的一款模块化可编程逻辑控制器&#xff08;PL…

苹果手机安装未上架APP应用测试教程

STEP 2&#xff1a;找到下载的描述文件&#xff08;如果没有找到&#xff0c;请到 设置 - 通用 - 描述文件 中查看&#xff09; STEP 3&#xff1a;安装描述文件 STEP 4&#xff1a;输入解锁密码安装描述文件 STEP 5&#xff1a;同意免责声明&#xff0c;安装描述文件 STEP 6…

开发知识点-Ant-Design-Vue

Ant-Design-Vue a-input a-input Vue组件 a-spin 加载中的效果 data字段 mounted钩子函数 Ant Design Vue 组件库 list-type“picture-card” 上传的图片作为卡片展示 name show-upload-list action :beforeUpload“handleBeforeUpload” :headers“customHeaders” :disabl…

springboot调用第三方接口json转换成对象

请求接口是一个比较常见的需求&#xff0c;接口返回一般是一个json类型&#xff0c;需要进行组装成对应的类&#xff0c;例 {"status_code": 200,"message": "success","data": {"cost": 286.6933,"bom_list": […

人工智能基础——Python:Matplotlib与绘图设计

人工智能的学习之路非常漫长&#xff0c;不少人因为学习路线不对或者学习内容不够专业而举步难行。不过别担心&#xff0c;我为大家整理了一份600多G的学习资源&#xff0c;基本上涵盖了人工智能学习的所有内容。点击下方链接,0元进群领取学习资源,让你的学习之路更加顺畅!记得…

使用ResponseSelector实现校园招聘FAQ机器人

本文主要介绍使用ResponseSelector实现校园招聘FAQ机器人&#xff0c;回答面试流程和面试结果查询的FAQ问题。FAQ机器人功能分为业务无关的功能和业务相关的功能2类。 一.data/nlu.yml文件   与普通意图相比&#xff0c;ResponseSelector训练数据中的意图采用group/intent格…

Vue 3 打印解决方案:Vue-Plugin-HiPrint

文章目录 1. Vue-Plugin-HiPrint 简介2. 安装和使用2.1 安装2.2 引入并注册插件2.3 在组件中使用 3. 配置和高级用法4. 示例应用5. 总结 &#x1f389;欢迎来到Java学习路线专栏~Vue 3 打印解决方案&#xff1a;Vue-Plugin-HiPrint ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f37…

x3daudio1_7.dll怎么解决?x3daudio1_7.dll丢失的5个详细处理方法

首先&#xff0c;让我们来了解一下X3DAudio1_7.dll丢失的原因。X3DAudio1_7.dll是一个非常重要的动态链接库文件&#xff0c;它负责处理计算机中的音频输出。然而&#xff0c;由于各种原因&#xff0c;例如软件安装错误、病毒感染、系统升级等&#xff0c;我们可能会遇到X3DAud…

超强C语言跨年烟花代码,精美无比,附源码分步解析

现在大家是不是都觉得程序员不懂浪漫&#xff1f;那真的大错特错&#xff0c;今天就让你们看看什么是程序员的浪漫&#xff01; 我们今天就来写写《烟花》表白程序&#xff0c;不要惊讶&#xff0c;不要激动&#xff0c;学会了快去拿给心中的那个人看&#xff01;&#xff01;…

【论文解读】针对生成任务的多模态图学习

一、简要介绍 多模态学习结合了多种数据模式&#xff0c;拓宽了模型可以利用的数据的类型和复杂性&#xff1a;例如&#xff0c;从纯文本到图像映射对。大多数多模态学习算法专注于建模来自两种模式的简单的一对一数据对&#xff0c;如图像-标题对&#xff0c;或音频文本对。然…

玩转ansible之参数调试和文件操作篇

更多IT技术文章&#xff0c;欢迎关注微信公众号“运维之美” 玩转ansible之参数调试和文件操作篇 01 剧本调试和帮助02 使用场景举例 上节我们学习了使用ansible进行软件安装&#xff0c;那么安装完软件后&#xff0c;就需要linux系统和软件配置修改了&#xff0c;对于linux主机…

Java程序设计2023-第八次上机练习

8-1简单文本编辑器 编写简单文本编辑器&#xff0c;该程序可以新建、打开、编辑和保存文本文件。当用户点击New时&#xff0c;新建一个文件&#xff0c;用户可以编辑文件内容&#xff0c;然后点击Save保存文件。用户点击Open时&#xff0c;选择一个已有文件&#xff0c;然后可…

leetcode:206. 反转链表

一、题目 函数原型&#xff1a; struct ListNode* reverseList(struct ListNode* head) 二、思路 要对链表进行反转&#xff0c;可以有两种方法&#xff1a; 1.改变链表中每个结点之间的指针域指向&#xff0c;最后返回尾结点即可。 2.新建一个链表&#xff0c;将原链表中的结点…

gorm之项目实战-使用gen以及定义表间关系

gorm之项目实战 ER图 关系整理 一对一关系&#xff1a; User 和 UserLog&#xff1a; 一个用户对应一个用户日志&#xff0c;通过 User 模型的主键与 UserLog 模型的外键建立一对一关系。 一对多关系&#xff1a; User 和 Teacher&#xff1a; 一个用户可以对应多个老师&…

win10网络和Internet设置

win10网络设置 win10进入网络设置的常用入口有两个 第一个入口 桌面右下角右键网络图标&#xff0c;然后打开“网络和Internt设置” 第二个入口 桌面的“我的网络”快捷方式&#xff0c;或者我的电脑进去后&#xff0c;左侧栏找到“网络” 右键“属性” 可以看到&#xff0c;…

【论文阅读VLDB13】Online, Asynchronous Schema Change in F1

Online, Asynchronous Schema Change in F1 ABSTRACT 在一个globally 分布式数据库&#xff0c;with shared data, stateless servers, and no global membership.进行一个schema演变。证明许多常见的模式更改可能会导致异常和数据库损坏&#xff0c;通过将破坏引起的模式更改…