EDA365电子论坛网

标题: 自制的MATLAB拼图游戏GUI界面版详解(下) [打印本页]

作者: baqiao    时间: 2021-1-18 09:43
标题: 自制的MATLAB拼图游戏GUI界面版详解(下)
本帖最后由 baqiao 于 2021-1-18 09:52 编辑 4 p  f- A( m4 n. r2 r
2 F' C4 i6 y& e* Z; W

摘要:这篇博文在早前本人写的介绍拼图游戏的基础上推出带有GUI用户界面的增强版,这里将通过上、中、下三篇博文详细介绍利用MATLAB GUI设计的拼图游戏完整实现过程,每篇都会附上相应代码及解释。下篇主要讲解拼图游戏中开始游戏并点击拼图块最终完成拼图的内部逻辑。下篇的要点如下:

点击跳转至拼图游戏全部文件下载页


1. 前言

    这篇博文紧接着前面一篇继续介绍MATLAB GUI拼图游戏的详细过程,这一篇终于到了介绍最后的拼图逻辑功能实现的部分了。本篇博文中拼图逻辑的代码与早前的基础版本相似,在其基础上做了一些改进使其能适应新加入的功能。因为GUI界面版内容较多,这里限于篇幅分成了上、中、下连续三篇依次讲解,可点击跳转查看拼图游戏完整代码。希望本文能给对MATLAB GUI界面设计或小游戏感兴趣的朋友有所启发。



# f5 \$ L8 K/ D7 ?: i, l2. 开始并完成拼图

    简单来说,我们这一节实现的功能是:点击“开始拼图”按钮后,在拼图区点击拼图块能够移动拼图并最终能够完成游戏,得到完整的拼好的拼图。效果如下:

    这里自上而下逐个函数讲解,首先和上篇的方法一样,我们打开之前设计好的包含GUI界面的fig文件,选中开始拼图的按钮,右击选择“查看回调”,点击“Callback”即可跳转至该函数的定义编辑文件中,在该函数中添加如下代码:


, A) h  ~7 h9 v8 D2 R
9 l5 d( I& p* F# X% g: s, D7 l; j  A8 e, _

% r+ b; I: E* j! S9 l/ u

    以上代码中,第3-18行其目的是为了获得当前初始的图片数据pic_data、拼图的阶数rank_Tag及所有控件的句柄handles,第19行调用拼图函数jigsaw,这个函数之前没有创建,这里新建一个m文件命名为jigsaw,在里面添加实现拼图逻辑的代码。


" [6 \! V5 c% S
3. 拼图主函数介绍3.1 分割拼图并显示

    在编写拼图游戏主函数前,先写几个主函数中要用到的子函数,这部分先在jigsaw.m文件中添加两个用于分割拼图并显示的函数。这节代码与前面的基础版本基本类似,与前面的思路相同,将整幅图像按阶数分成对应份数并用数字表示。不过这里因选择的图片尺寸不一,因此需要先计算每块拼图的宽高,可由图片的整体尺寸除以拼图阶数求得;同时因为不是默认的单一坐标系,在显示拼图的时候为避免混乱需要指定显示拼图的坐标轴。将图片分割并显示的函数的代码如下:

' c! ]3 M" T- n. v

1 b3 F8 x6 O5 p+ A& E7 K8 O
1 f# W8 @6 e  m4 x, F* t# N$ `3 v0 G4 H% s5 \& f9 u, Y0 k

    在以上代码中,choose函数的输入参数除了image, index还加入了pic_data, rank_Tag,分别是用于拼图的图像数据以及当前拼图阶数。在对图片进行分割时应考虑到拼图的阶数,因此在代码第10行按照拼图块标记选择原图中相应数据进行赋值。drawmap函数中加入了handle表示要显示拼图的坐标轴句柄,以便在第31行指定坐标系。

3.2 移动拼图

    为了实现拼图的移动,需要知道鼠标点击的位置,这里鼠标位置所在的拼图块的行列号由row, col传入。判断是否移动拼图的标准是点击位置是否在空白拼图块(标号为0)的4邻域内(行号或列号相差1),因此我们只需比较row, col加或减1的标号矩阵的值是否为0,如为0表示位置相邻则交换两个位置上的值。

    值得注意的是为保证程序不会出错,需要先判断row, col的值是否在可点击范围内,同时为了实时显示游戏过程中的移动步数,有必要声明一个变量用于计数。移动拼图块的代码如下:

/ r% H0 x. v4 y& |3 z) J

/ G2 \9 u) o. R& V3 y; h# J+ I3 e6 V8 k8 w! Y# d) V0 o0 B
/ j- r! v8 ?1 z* C3 i7 s/ Y: d" E

    代码通过改变标记矩阵tag后根据tag的值显示拼图对应拼图块达到逻辑和显示上的拼图移动,第33-39行判断拼图是否发生移动并据此记录移动拼图块的步数,并显示在显示步数的文本标签上。

3.3 打乱拼图

    打乱拼图采用的是模拟手动打乱拼图的方式,不断随机产生点击位置坐标,利用上面编写的移动拼图函数,不断随机打乱拼图。随机动作的次数应随拼图的阶数而增加,重复一定次数可将拼图完全打乱,返回一个打乱之后的标记矩阵。打乱拼图的代码如下:

0 ^/ {9 p2 X( M! g- \" K
  q" L' A/ d/ C, h- I

* L/ K# z4 }: r/ a, @5 k* ]9 R, _8 c3 l5 r/ K; t2 {
3.4 拼图主函数

    主函数的设计思路是首先将标记矩阵打乱,并按照标记矩阵中的排列显示拼图块,然后需要获得鼠标点击处的位置坐标以移动拼图,每次移动后判断拼图顺序是否已经正确,顺序正确后结束游戏。获取鼠标点击位置坐标的方法是利用figure的WindowButtonDownFcn属性定义一个坐标获取的回调函数。当在图上按下鼠标的时候,就会自动执行回调函数来获取坐标值。主函数的代码如下:


1 y% e! j$ B8 w' u0 F8 G0 v9 J* @
+ u6 ^7 V- @: h% D5 _
$ F+ S& ]" T( p% N

    主函数中调用了mask_number其作用在于根据控件CheckBox的勾选状态决定是否在拼图块上显示数字提示,这个在前面的代码中已多次提及了。第25行是设置windowButtonDownFcn属性的回调函数,gcf表示当前图形窗口句柄,ButtonDownFcn是回调函数名,@ButtonDownFcn表示其函数句柄,后面handles, pic_data, rank_Tag是回调函数的输入参数,整条代码就是设置当在当前图形窗口中点击鼠标时就会转而执行ButtonDownFcn函数,该函数的代码在下节介绍。


. S; o& i5 {  t7 \$ }8 Y1 y, W
4. 鼠标事件回调函数

    每次点击鼠标时就会执行一次回调函数,因此可以在回调函数中编写程序获取当前鼠标位置并据此移动一次拼图,然后判断拼图是否完成。定义回调函数ButtonDownFcn( ),输入参数src、event为系统约定变量,handles, pic_data, rank_Tag分别为需要用到的控件句柄、拼图的图片数据、拼图阶数,函数代码如下:


! p. f* A+ R# Y( p! s/ w& Q
4 G, K) @" i+ N
$ Y1 i3 @; ?! \3 [. S! e3 A' v
, B1 k- c* w; `4 F4 p. `1 t

【代码解释】

    代码第6行先判断全局变量flag的值,决定是否执行下面的操作(是否相应鼠标点击),由前面的代码可知当只有在重新选择图片、选择难度(阶数)的时候flag的值会被置为false来防止误操作,而当点击运行游戏按钮时该值会被重新置为true使程序运行。第7-9行获取鼠标点击处的坐标实际值,我们需要转换成拼图块的行列数,所以第11-15行获得拼图块的长宽,并由此计算行列数。第18行判断鼠标点击位置是否在拼图的显示区域内,第19-20行调用上面的函数按点击位置移动拼图并显示。第25-29行产生一个顺序的矩阵,并将当前的标号矩阵与该矩阵进行比较,以判断拼图是否已拼好。第31-36行在拼图拼好后显示完整图像并提示完成。第37行重新将flag的值置为false在重新开始游戏前不能再移动拼图。


9 y% z6 a, R9 [4 [% P/ a9 Z
作者: yin123    时间: 2021-1-18 10:52
自制的MATLAB拼图游戏GUI界面版详解(下)




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2