更新:

没有素材或者.mat文件看着博客也比较难实现,下面是完整的游戏文件

链接:https://pan.baidu.com/s/1CH_vFQQ_m2rIXde-VtkPWg

提取码:uo2x

游戏画面:

注:文章开始写的时候还没有考虑到高阶的扩展的问题,高阶扩展部分的代码更具有普遍性,可以直接跳过前面的代码设计看高阶扩展部分。

游戏介绍

游戏玩法来源

游戏的玩法规则并非原创,最早看到是多年前百度魔方吧有人制作了可以在网页上玩的版本,同时还制作了4×4版本。网页连接很早之前就失效,作者也不可考。感谢作者制作了这样一个有意思的小游戏。

设计参考

主要来自桥上风景楼上的你的博客,基于MATLAB的拼图游戏设计(图文详解,附完整代码)https://blog.csdn.net/qq_32892383/article/details/79219110

两个游戏有很多相似之处,这篇文章条理很清晰,对于整个编写过程带来了很大帮助。

规则和功能

小游戏的基本规则:如图所示,点击某一个方块自身及相邻的方块数值加一,到达最大值(设定的是9)循环回最小值(1),最小值的索引不是0而是1对应了Matlab的索引下标是1起始。

游戏目标:通过点击方块使所有的方块的值相同。

当玩家完成后显示步数和胜利语句。

一些定义

游戏画面有长宽两个维度,同时还有数字循环的次数。

仿照魔方将维度定义为m×n,可以在后续看到这个游戏的长宽不一定需要相等。

将一个循环中有的数字个数称之为深度。

设计逻辑

仿照桥上风景楼上的你的文章也画了一张流程图。两个游戏的基本逻辑相似。

前期准备

首先是绘制这几张图片(我是用画图软件画的)。

然后用imread()读入Matlab,直接拼接成一长条。

img=[];

for k=1:9

img=[img,imread(strcat(num2str(k),'.png'))];

end

imshow(img)%显示

imwrite(img,'puzzle1.png');%输出到文件目录

本来打算用小方块来实现,后来发现拼合成长条直接用也很方便。使用长条形的素材,构造一个GetImg函数以获取第k个数字的图片。

function X=GetImg(img,k)

%取出第k张图

X=img(:,100*(k-1)+1:100*k,:);

end

绘制游戏画面

游戏画面的9个数字可以用一个3×3的矩阵来标记。绘制游戏画面的函数drawmap就依靠得到的状态,也就是3×3的标记矩阵来显示,代码如下

function drawmap(A)

im=imread('puzzle1.png');

img=uint8(zeros(300,300,3));%预分配,且类型需要为unint8

% 对要显示的图片进行赋值

for row=1:3

for col=1:3

img(1+(row-1)*100:100*row,1+(col-1)*100:100*col,:)=GetImg(im,A(row,col)); %将A矩阵中的数字和图片对应

end

end

imshow(img)%显示画面

end

用以下语句测试,矩阵A和显示的每个数字都对应

A=[1,2,3;4,5,6;7,8,9]

drawmap(A);

打乱函数

虽然没有严格的证明,但是经验得出(没有遇到随机的打乱无法复原的情况)任意状态应该都是可以复原的,所以打乱就可以很简单用随机生成的9个数字来实现,并不需要模拟人为打乱。任意状态是否都能复原还有待证明。

function A=Disrupt()

A=unidrnd(9,3,3);随机生成值在1到9之间的3×3矩阵

drawmap(A);

end

主函数和规则

Matlab提供了两种获取鼠标坐标的途径,一个是ginput()函数,会有一个十字光标进行定位;另一个利用figure的WindowButtonDownFcn属性,在figure界面点击鼠标可以调用回调函数,实现一些功能。游戏的主函数如下

function puzzle()

%% 主函数

loading()%开场动画

global Tag;%Tag是标记矩阵,定义成全局变量,方便传递参数

Tag=Disrupt();%将标记矩阵的排列顺序打乱Tag_A;

global count;%计算步数,也设为全局变量

count=0;

set(gcf,'windowButtonDownFcn',@ButttonDownFcn);%点击鼠标时调用ButttonDownFcn函数

鼠标点击时调用ButttonDownFcn函数,ButttonDownFcn函数中实现游戏的规则和画面的刷新,比较偷懒没有分模块来写,所有都写在一块了。图像的大小时300×300,所以坐标值/100向上取整(ceil函数)转化为矩阵对应的坐标。用四个if语句来实现了规则。最后检测是否胜利,可以用标记矩阵和k*ones(3,3)比较,也可以逐项比较每个元素是否相等。达成胜利条件,输出包含还原步数的消息。

function ButttonDownFcn(src,event)

pt = get(gca,'CurrentPoint');

y = uint8(ceil(pt(1,1)/100));

x = uint8(ceil(pt(1,2)/100));%获取点击的位置转化为矩阵中的坐标

global Tag

global count%声明全局变量

if x>=1&&x<=3&&y>=1&&y<=3%点击位置满足才执行

count=count+1;%计算步数

Tag(x,y)=Tag(x,y)+1;

if x<3 %四个if实现规则

Tag(x+1,y)=Tag(x+1,y)+1;

end

if x>1

Tag(x-1,y)=Tag(x-1,y)+1;

end

if y<3

Tag(x,y+1)=Tag(x,y+1)+1;

end

if y>1

Tag(x,y-1)=Tag(x,y-1)+1;

end

Tag(Tag==10)=1 ;

end

drawmap(Tag);

%胜利条件

for k=1:9

if Tag==uint8(k*ones(3,3))

msgbox(strcat(num2str(count),' !You win!')); %提示完成信息

pause(5);%延迟

close all %游戏结束,关闭所有图像窗口

end

end

end

至此所有的工作都完成了,运行puzzle()函数就能可以玩了。

谜题解法

我的解法利用了它的对称性,优化一下步数大概在40-60之间。欢迎交流解法。

叙述可能有些繁杂,有时间再详写。

扩展

以上整个3×3的拼图就算是完成了,但是功能并不灵活。经过一些小修改可以实现十分丰富的玩法。

更多阶数和深度

在这个代码的基础上制作更高阶的版本也非常容易实现。在puzzle()函数中引入3个全局变量dim_x,dim_y和depth,编写setdim()分别来设置维数。

puzzle.m修改如下:

function puzzle()

%% 主函数

%loading()%开场动画

global Tag;%Tag是标记矩阵,定义成全局变量,方便传递参数

global count;%计算步数,也设为全局变量

count=0;

global dim_x;

global dim_y;

global depth;%维度

[dim_x,dim_y,depth]=setdim(4,4,6);

Tag=Disrupt();%将标记矩阵的排列顺序打乱Tag_A;

set(gcf,'windowButtonDownFcn',@ButtonDownFcn);%点击鼠标时调用ButttonDownFcn函数

setdim()函数如下:

function [dim_x,dim_y,depth]=setdim(x,y,d)

dim_x=x;

dim_y=y;

depth=d;

end

同时在其他的函数中也需要进行一些修改

绘制画面根据dim_x,dim_y绘制画面,

function drawmap(A)

im=imread('puzzle1.png');

img=uint8(zeros(100,100,3));%预分配,且类型需要为unint8

global dim_x

global dim_y

% 对要显示的拼图进行赋值

for row=1:dim_x

for col=1:dim_y

img(1+(row-1)*100:100*row,1+(col-1)*100:100*col,:)=GetImg(im,A(row,col));

end

end

imshow(img)%显示

end

标记矩阵的数值变为1到depth,维度为dim_x,dim_y

function A=Disrupt()

global dim_x;

global dim_y;

global depth

A=unidrnd(depth,dim_x,dim_y);

drawmap(A);

end

回调函数,基本是将3×3的3换成dim_x,dim_y,当数字超过depth变为1,胜利条件变为与1到depth的dim_x×dim_y的矩阵比较。

function ButttonDownFcn(src,event)

pt = get(gca,'CurrentPoint');

y = uint8(ceil(pt(1,1)/100));

x = uint8(ceil(pt(1,2)/100));

global Tag

global count

global dim_x

global dim_y

global depth

if x>=1&&x<=dim_x&&y>=1&&y<=dim_y%点击位置满足才执行

count=count+1;%计算步数

Tag(x,y)=Tag(x,y)+1;

if x

Tag(x+1,y)=Tag(x+1,y)+1;

end

if x>1

Tag(x-1,y)=Tag(x-1,y)+1;

end

if y

Tag(x,y+1)=Tag(x,y+1)+1;

end

if y>1

Tag(x,y-1)=Tag(x,y-1)+1;

end

Tag(Tag==depth+1)=1 ;

end

drawmap(Tag);

%胜利条件

for k=1:depth

if Tag==uint8(k*ones(dim_x,dim_y))

msgbox(strcat(num2str(count),' !You win!')); %提示完成信息

pause(5);%延迟

close all %游戏结束,关闭所有图像窗口

end

end

end

只需修改这几个小地方,通过setdim()即可调整设置不同维度

2×2×7

3×3×2

这个换成0和1可能更好一点

更高阶

不等阶

修改规则

经过修改回调函数可以实现别的规则,新规则同样适用于不同的阶数

1.注释掉回调函数的第10行

%Tag(x,y)=Tag(x,y)+1;

规则就改为被点击的方块数值不发生变化,相邻方块数值加1。

2.更改为被点击的方块所在的行列+1

代码修改为

if x>=1&&x<=dim_x&&y>=1&&y<=dim_y%点击位置满足才执行

count=count+1;%计算步数

Tag(x,y)=Tag(x,y)+1;

if x

Tag(x+1:dim_x,y)=Tag(x+1:dim_x,y)+1;

end

if x>1

Tag(1:x-1,y)=Tag(1:x-1,y)+1;

end

if y

Tag(x,y+1:dim_y)=Tag(x,y+1:dim_y)+1;

end

if y>1

Tag(x,1:y-1)=Tag(x,1:y-1)+1;

end

Tag(Tag==depth+1)=1 ;

end

效果如下:

3.其他

当然也可以设计成以上两种规则的混合,还可以设计成对角相加,或者其他一些更奇怪的规则。胜利条件也可以被设置得更苛刻,比如只有都为1才算时胜利。未来会加入更多的修改。

问题和改进

对于新规则,打乱可能存在问题,没有严格的证明其他任意阶数的任意状态和任意规则都可以复原

规则部分没有模块化,不便于修改规则,可以设置一个函数句柄,来对规则进行选择

缺少一个GUI界面以便选择更多模式,记录最好成绩等

可以考虑增加一个计时模式

对于某一规则可以写一个通用解法

欢迎提出建议或意见

后记

算是写出的第一个真正完善的程序,程序语句可能也不够优雅。游戏解法方面,除了最原始的规则和阶数,目前对于更高阶数和新设计的解法也没什么好的解法,运气好可能能解出来。

欢迎交流解法和游戏相关规则设计的问题。

matlab模拟小游戏,基于MATLAB的小游戏(puzzle)相关推荐

  1. matlab模拟频谱仪,毕业设计基于MATLAB的声音信号频谱分析仪源代码V3.1(手机版)...

    <[毕业设计]基于MATLAB的声音信号频谱分析仪源代码.doc>由会员分享,可免费在线阅读全文,更多与<毕业设计基于MATLAB的声音信号频谱分析仪源代码(V3.1)>相关文 ...

  2. matlab模拟Fraunhofer衍射,基于Matlab的夫琅禾费衍射光学仿真.doc

    基于Matlab的夫琅禾费衍射光学仿真 基于Matlab的夫琅禾费衍射光学仿真 摘要 计算机仿真技术是以多种学科和理论为基础,以计算机及其相应的软件为工具,通过虚拟试验的方法来分析和解决问题的一门综合 ...

  3. matlab模拟换热过程,基于MATLAB的风冷式翅片管冷凝器的仿真模拟

    基于MATLAB的风冷式翅片管冷凝器的仿真模拟 孙建新南晓红 (西安建筑科技大学环境市政工程学院西安 710055) 摘要:本文利用分布稳态参数法建立了翅片管换热器的数学模型,并用MATLAB语言编制 ...

  4. matlab模拟流动传热,基于MATLAB的快速式汽-水换热器传热与流动特性研究

    基金项目:国家自然科学基金项目 (项目编号: 50776055) ;山东省自然科学基金项目 (项目编号: Y2007F10) 基于 MATLAB的快速式汽 -水换热器传热与流动特性研究 张艳乔1 ,张 ...

  5. matlab模拟方孔衍射,基于MATLAB衍射的矩形孔实验模拟

    翌 毫研夯一一_ 乜业岍九 基于 MATLAB衍射昀矩形孔实验旗拟 张 亚 陈冬冬 成海英 /盐城工学院 [摘 要]根据物理光学中光的矩形孔衍射理论,利用 MATLAB工具编写程序进行实验模拟,绘 出 ...

  6. matlab模拟断层成像,基于matlab和nirfast的荧光分子断层成像

    基于matlab和nirfast的荧光分子断层成像 关注次数: 40 下载次数: 3 文件大小: 21.36M 下载需要积分: 1 代码分类: 开发平台: matlab 上传会员: yhcpp 下载代 ...

  7. matlab模拟光伏发电,基于Matlab/Simulink的三相光伏发电并网系统的仿真

    第 29卷 第 10期 2013年 10月 电网与清洁能源 Power System and Clean Energy 蠲 -■ Clean Energy Vo1.29 No.10 0ct.2013 ...

  8. MATLAB模拟声压分布,基于Matlab仿真软件构建圆形压电晶体三维模型

    1.超声探头发射声场的研究 1.1波源轴线上的声压分布 在连续简谐纵波且假定超声波传播无衰减的情况下,液体介质中圆形压电晶片上一点波源ds辐射的声场在波源轴线上P点引起的声压为: 根据波源叠加原理,将 ...

  9. matlab中liccode函数,基于matlab车牌识别系统设计与实现(最终版)

    <基于matlab车牌识别系统设计与实现.doc>由会员分享,可在线阅读全文,更多相关<基于matlab车牌识别系统设计与实现(最终版)>请在www.woc88.com上搜索. ...

  10. Matlab之DNN:基于Matlab利用神经网络模型(epochs=10000000)预测勒布朗詹姆斯的2018年总决赛(骑士VS勇士)第一场得分、篮板、助攻

    Matlab之DNN:基于Matlab利用神经网络模型(epochs=10000000)预测勒布朗詹姆斯的2018年总决赛(骑士VS勇士)第一场得分.篮板.助攻 目录 输出结果 预测勒布朗詹姆斯的20 ...

最新文章

  1. mysql try catch_C# try catch finally:异常处理
  2. html游戏源妈简单,最简单的HTML5游戏——贪吃蛇
  3. System Center 2012 Process Automatic
  4. python使用线性回归实现房价预测
  5. 中tr不能显示字符_垃圾文本识别中基本操作指南和错误总结,第三部分
  6. Mysql数据库知识总结
  7. Python排序算法---冒泡排序
  8. iphone pop服务器没有响应,iPhone 6 Plus跳屏或者触摸失灵的解决办法
  9. 国内外各大网站镜像源
  10. 金角大王 python_【51CTO学院三周年】 老男孩python全栈心路
  11. matlab 普通数值计算,数值计算方法(MATLAB版)
  12. 【算法】基于AOE网的关键路径算法
  13. 基于模拟退火优化算法的的并行车间机器优化调度附Matlab代码
  14. PLC 定时器指令计数器指令比较赋值指令的总结
  15. OpenMP学习笔记之常用指令parallel/sections/critical 其余待续
  16. word小技巧--怎么去掉Word文档封面页码的方法
  17. Navicat 创建数据库
  18. 更改xshell远程服务器的终端字体颜色并突出显示用户名
  19. 计算机视觉与脑电数据等应用于驾驶员的疲劳状态检测综述
  20. 数码相框解决方案深度分析

热门文章

  1. 大学生网上卖鞋子,靠自己双手实现了财富梦
  2. python高效办公
  3. 窗口最大化后没有显示按键_如何通过一次按键将一台显示器上的所有窗口移动到另一台显示器上
  4. 用matlab验证罗尔定理,高等数学一习题3.1答案
  5. 伺服驱动器接收脉冲数,齿轮比,发送电机脉冲数关系
  6. 如何快速查看你的笔记本电池健康报告
  7. withCredentials: false,
  8. access内置函数:(适用access2000)
  9. STM32CubeMX | 32-使用硬件FMC驱动TFT-LCD屏幕(MCU屏)
  10. 统计词频-生成词云-数据分析报告(python R语言)