【连载爽文 Part.2】4*4Puzzle ——基于MATLAB App Designer 的一例游戏。-程序员宅基地

技术标签: matlab  数学建模  游戏  

6.写在前面

我要特别感谢一下CSDN这个技术平台,在昨天我发布了我的第一篇blog ,就被平台推流,而且今天早晨收到此篇blog 进入【CSDN每天最佳新人】榜单的消息,欣喜若狂,受宠若惊。感到平台对新人作者和原创文章的无限尊重与无穷善意,我想这也是各领域的能人异士,乐于在本平台分享知识、交流心得的原因吧!也衷心祝愿本平台越来越好(词穷但认真)!

本篇blog 直接从chap 6 开始写了,此次【连载爽文 Part.2】书接上回,因为本人语言能力有限,代码也不尽如人意,所以昨日拖拖拉拉只完成了App Designer 准备工作的一部分,但已经4000+ characters 。担心文字冗长乏味,使各位看官老爷觉得枯燥无趣,只略施小计,讪讪在文章标题前加了这么个噱头。再行连载本篇是为了与诸位共同探讨学习app designer 的基本使用技法和思路,也是一例简单的Matlab 应用程序的实践。(下图取自我发表的第一篇blog )

7. App Designer 的样板设计 

样板设计就是应用程序的交互排布了,我将app分为了显示区、交互按钮区和puzzle 解谜区3个区域,基本样板如图(显示区为左上、交互按钮区为左下、puzzle 解谜区在右侧):(该图是puzzle 完全开发后初次启动运行的样子(只交互了该puzzle 的startupFcn ))

上图可知。我们制作了四个功能按钮,分别为START ,CHECK ,SHOW ,&RESET 。

START:通过对函数F(在上篇有介绍),随机出一个新的puzzle至右侧解谜区。

CHECK:检测解谜区的puzzle 完成情况,并且输出您完成该puzzle 的步数(此值在闭区间[4,16]之内)这两段输出文档将生成在左上方的显示区中。

SHOW:将START 键产生的puzzle a 完全展示在解谜区,并以二进制4*4 矩阵的形式将答案输出于显示区。

RESET:完成一次puzzle 后按下,会将右侧解谜区完全清除(呈上图的样子)。说直白点呢,就是相当于关闭游戏,又重新打开了一下。

解谜区如何交互呢?因为信号灯Lamp(上图16圆)没有交互属性(中国话就是说,这个灯灯它点不了)所以在16 个信号灯Lamps 下面(注意设置图层关系)又藏了16个按钮Buttons以控制信号灯的颜色,交互之后可以改变Lamp 的颜色(答案正确变绿,答案错误变红)。

反思:其实这里可以用组件库的【图像】组件,可以更完美且更便捷地模拟本篇开始的图片那样——点击图案→正确则显示彩色图像块,错误则显示黑白色的图像块。这种方法且不说虽需要制作2*4*4,两套图像(一套正确彩色,一套错误黑白)和初始图像1*4*4个问号吧(假设)。共制作33张大小统一的图片。但是它快啊(因为它善),交互起来很舒服。

不说这么多,意思就是:我太懒了我不想干你们来吧。

8.显示区

我很笨很懒,图示的标签显示因为要多次换行,所以我拖入了3个固定标签,以及3个变量标签。稍加排版(这里有【*山代码】之嫌,且虚心求教!不在话下。)

*3个固定标签即是这三张

从左至右依次服务于 START&RESET(共用图例1)、SHOW、CHECK。

这三个标签的内容是固定的(即【.Text 】的解析不随交互而变化)只需要改变这三个组件的【.Visible 】解析属性,即可完成按钮和显示区内容的切换。

——这操作简直是拯救人(猪)脑的不二法门。

*3个变量标签即是这三张

初值为YroN 的标签用以表示判定puzzle 完成情况;

初值为Times 的标签以表示步数;

初始DO NOT EXIST 标签以展示puzzle 的整体分布。

在chap7有提到过这些标签与按钮区的交互方式!不再赘述咯。

9.解谜区的交互方式 以及 前置脚本!

我制作了交互解谜区16按钮的方式

以及五个.mlx 脚本,脚本分别命名为Wre、Sow、Cln、Able、dAble。

名称呢,分别取自英文Where、Show、Clean、Able、disAble。接下来为大家介绍用途:

9.1 解谜区的交互

此脚本用以查找每次按键之后,我们到底按在哪里了?按下的答案对不对。

解谜区的交互我直接写到app designer 里面区了,因为很简短,但是调用的组件名称又不能标准化。所以也是开开心心写了16份相似的代码(只有调用名称有所差异)。蛮整齐的嘞~

            a=evalin('base','a');
            if a(1)==1
                app.a_1.Color='g';
            else
                app.a_1.Color='r';
            end

            t=evalin('base','t');
            t(1)=1;
            assignin('base','t',t)
            
            app.Button_1.Enable=0;

注意看,这个app.a_1 是第一个灯泡(此后的灯泡按4*4方阵的元素位置排列,分别是a_1、a_2...a_16)当你按下解谜区第一行第一列的button,就会开始判断我们生成的puzzle棋盘的第一个元素a(1)是否为1,1返还Color='g',0返还Color='r'。我们有必要解释一下这个t,因为这个t是在交互START按钮后生成的,用以记录我们按下按钮的位置。

app.Button_1.Enable=0;        库库破釜沉舟,按完这个按钮就不让你再按了。

9.2 Wre.mlx

此脚本以define puzzle 是否完成;
并且定位完成的通路位置;

e=zeros(4);
for n=1:16
    if t(n)==1
        e(n)=a(n);
    end
end
cross=[sum(diag(e)),sum(diag(flipud(e)))];
col=sum(e);                                 % only col(1)==4
row=sum(e,2)';
mix=[cross,col,row];                        % mix 是一个1*10的列表

得到s;
当没有通路时,s=0;
当有通路时,s的值是通路的位置;

s=find(mix==4);
def=size(s);def=def(2);
if def==0
    s=0;
end

将位置参数转化为字符串str;

if s==0
    str='The puzzle is not finished';
elseif s==1
    str='main diagonal';
elseif s==2
    str='sub diagonal';
end
if s>2 && s<=6
    str=['Puzzle done with column ',num2str(s-2)];
end
if s>6 && s<=10
    str=['Puzzle done with row ',num2str(s-6)];
end

9.3 Sow.mlx

此脚本以展示底层puzzle ;

傻瓜代码,只展示一部分,第1列 lamp 展示;

if a(1)==1
    app.a_1.Color='g';
else
    app.a_1.Color='r';
end

if a(2)==1
    app.a_2.Color='g';
else
    app.a_2.Color='r';
end

if a(3)==1
    app.a_3.Color='g';
else
    app.a_3.Color='r';
end

if a(4)==1
    app.a_4.Color='g';
else
    app.a_4.Color='r';
end

毫无技巧可言。可以讨论 

9.4 Cln.mlx

此脚本以将所有的Lamp复原至灰色;

下为部分代码:(同样为第一列)

app.a_1.Color=[0.80,0.80,0.80];
app.a_2.Color=[0.80,0.80,0.80];
app.a_3.Color=[0.80,0.80,0.80];
app.a_4.Color=[0.80,0.80,0.80];

9.5 Able.mlx & dAble.mlx

此脚本以改变按钮button的交互性质。

顾名思义,前者使button 可交互,后者将button 变不可交互(分别为下方上、下两条代码)。

app.Button_1.Enable=0;

app.Button_1.Enable=1;

10.startupFcn 以及 按钮交互区的回调!

终于来到了自认为很关键的部分,至此上文已经达到1500+字数了~本章会为大家介绍四个按钮的功能以及源代码!

10.1 startupFcn回调

直接展示可编辑段:

            evalin('base','clear variables')
            dAble
            
            app.START.Enable=1;
            app.RESETButton.Enable=0;
            app.SHOWButton.Enable=0;
            app.CHECKButton.Enable=0;

此时为应用刚打开的情形(参考样板设计图例),

所有的解谜区按钮不可交互,

START按钮可以交互,RESET、SHOW、CHECK按钮则无法选中(可以躲元气弹了)。

10.2 START 按钮回调

            app.start.Visible=1;
            app.check.Visible=0;
            app.YorN.Visible=0;
            app.Times.Visible=0;
            app.show.Visible=0;
            app.atext.Visible=0;
            
            app.START.Enable=1;
            app.RESETButton.Enable=1;
            app.SHOWButton.Enable=1;
            app.CHECKButton.Enable=1;
            
            Cln
            Able
            F
            assignin('base','a',a)
            t=zeros(4);
            assignin('base','t',t)

第一部分为标签的可视化,交互之后只能看到第一段文字(显示区的第一固定标签)

第二部分为按钮去的可交互调用,此时什么都可以按了。

第三部分先是Cln 将所有的Lamp复原至灰色,然后使Lamp 下的Button 可交互了。

再运行函数F(上篇内容),将a写入工作区,建立全0矩阵t,写入工作区。

assignin 函数和evalin 函数是非常重要的,否则会出现没有写入的情况,

(一般写入和调用同时存在,逻辑为:写入——调用——工作区的数据处理——再写入)。

10.3 CHECK 按钮回调

            app.start.Visible=0;
            app.check.Visible=1;
            app.YorN.Visible=1;
            app.Times.Visible=1;
            app.show.Visible=0;
            app.atext.Visible=0;
            
            app.START.Enable=1;
            app.RESETButton.Enable=1;
            app.SHOWButton.Enable=1;
            app.CHECKButton.Enable=1;
            
            a=evalin('base','a');
            t=evalin('base','t');
            Wre
            assignin('base','a',a)
            %assignin('base','str',str)
            app.YorN.Text=str;
            
            
            t=sum(sum(t));

            app.Times.Text=num2str(t);

第一二部分同样是对【标签可视化】和【按钮交互性】的定义,乖的宝宝已经可以自行理解了。

第三部分即是 assignin 函数和evalin 函数的一个英语,因为Wre 脚本会用到a,我们需要先行调用(此部分虽然没有对a进行任何处理改动,但为了美观和杜绝软错误,我们还是再写入了)

注意app.YorN.Text=str;其代码意义就是将YorN 这段标签的Text 内容改为str ,str 的定义在Wre.mlx 中有提到,动动小手指向上翻翻看吧~

这个t则是我们和解谜区按钮交互的位置,通过sum(sum()) 两次求和,生成t(times) 用于度量次数,值得注意的是.Text的解析只能被【字符串类型】赋值,甚至字符串构成的向量或矩阵,都无法用于改变标签的内容。

10.4 SHOW 按钮回调

            app.start.Visible=0;
            app.check.Visible=0;
            app.YorN.Visible=0;
            app.Times.Visible=0;
            app.show.Visible=1;
            app.atext.Visible=1;
            
            app.START.Enable=1;
            app.RESETButton.Enable=1;
            app.SHOWButton.Enable=1;
            app.CHECKButton.Enable=0;
            
            dAble
            
            a=evalin('base','a');
            Sow
            assignin('base','a',a)
            
            app.atext.Text=strcat(num2str(a(1,:)),10,num2str(a(2,:)),10,num2str(a(3,:)),10,num2str(a(4,:)));
            
            t=zeros(4);
            assignin('base','t',t)

 一二部分跳过

SHOW按钮按了之后,解谜区就不可用了。这里又有一个小技巧,就是如何让app 的标签组件进行分行输出(对,没错,就是那条最长的):

app.atext.Text=strcat(num2str(a(1,:)),10,num2str(a(2,:)),10,num2str(a(3,:)),10,num2str(a(4,:)));

就是按照a的四行,每行转为字符串,然后分段输出。

哇,真的是太神奇辣~(章鱼哥音)

——虽然试了很久如何分段输出:所以不是我笨,我真的只是懒。

10.5 RESET 按钮回调

            app.start.Visible=1;
            app.check.Visible=0;
            app.YorN.Visible=0;
            app.Times.Visible=0;
            app.show.Visible=0;
            app.atext.Visible=0;
                        
            evalin('base','clear variables')
            dAble
            Cln
            
            app.START.Enable=1;
            app.RESETButton.Enable=0;
            app.SHOWButton.Enable=0;
            app.CHECKButton.Enable=0;

样板设计的时候已经介绍过RESET 按钮了,就是将应用程序初始化一下。

(结束了罪恶的一生,然后开始了罪恶的下一生。)

11. Last 写到最后

本篇插入的Matlab 代码段,除了chap 9 的五个脚本都是App Designer 的可编辑部分!

果然不出所料,写这篇blog的时候出现了闭环。因为当我想要介绍前置脚本Wre.mlx 的时候,就一定会提到如何交互解谜区的16按钮,要介绍如何通过按按钮来进行答案监测,又需要写出START 按钮的初始赋值情况,当我决定先写START按钮的回调时,又发现按钮里包含了前置脚本。嚯嚯嚯,所以就按我们(我自己)最能理解的地方开始解释咯~

本次的蓝色部分仍然为讨论部分,手机版可能看不到,认准【可以讨论】字样。

此次连载新增了红色部分,是我觉得写App Designer 时很重要的技巧,也供讨论,畅所欲言。

各功能按钮会导致有一些按钮不能用,这里只tip 上了源代码而不能尽其言。是我的失职,如果想玩一下的话,我可以打包发给你们u~

作者本科在读,但非计算机及相关专业的学生。所以觉得对互联网时代的普遍认知以及观念还不能尽然,代码风格可能遭人唾弃(虚心接受)。但我相信检验出真理这句话。唯有实践才能回溯性的构建思想,解放思想,推陈出新。

本篇也是作者第一次编写APP designer 并且第一次在CSDN发布blog,一路写来,还是有很多大家可以用的上的思路和技巧(是我自己这么想)总之谢谢大家的喜欢!

完结撒花

 这个puzzle 的爽文至此结束了!再次感谢一下CSDN和CSDN平台上勤奋的IT小猴子们~

希望和大家一起思考,多多讨论。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_68271418/article/details/136054004

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法