配套课件可访问https://github.com/BIMK/MATLAB下载,是安徽大学Matlab本科教学课件,逻辑清晰,简洁明了,颇为实用,用来入门再好不过(机器学习方向)。
本系列博文是课后练习的个人解答,通过几个小实验展示matlab基本语法和技巧。接触Matlab也有几年了,略有心得,分享给大家。
1. 熟悉matlab图形界面编程的基本方法
2. 掌握基本的非可视化GUI编程语法
3. 掌握回调函数的使用方法
1. 编写一个连连看游戏程序。
2. 两个数字相同且可通过三条或以内直线连接(不经过其它方格)的两个方格,可同时选中并消除。
3. 当有两个按钮被按下时,判断它们是否可连接;如果可连接则消除它们,否则取消选中它们
垂直判断:遍历每个红色的方格。如下图所示,每个红色方格可唯一决定一条由起点经过该方格到终点的最短路径;判断该路径上是否存在障碍即可。
水平判断:遍历每个红色的方格。如下图所示,每个红色方格可唯一决定一条由起点经过该方格到终点的最短路径;判断该路径上是否存在障碍即可。
代码(详见注释)
function task3()
close all;
global M;
global judge;
M = ones(12,12);
M([1,end],:) = 0;
M(:,[1,end]) = 0;
judge = [];
fig = figure('MenuBar','none','ToolBar','none','NumberTitle','off','Position',[0,0,500,500]);
movegui(fig,'center');
for i = 1:10
for j = 1:10
h(i,j) = uicontrol('style','togglebutton','Units','Normalized',...
'Position',[(i-1)/10,(j-1)/10,0.1,0.1],...
'FontSize',12);
h(i,j).String = num2str(randi([0,9]));
h(i,j).Callback = @(~,~)link(h,i,j);
end
end
for i = 1:10
for j = 1:10
h(i,j).Callback = @(~,~)link(h,i,j);
end
end
end
% 回调函数
function link(h,i,j)
global M;
global judge;
% 若上步已经处理完毕,恢复按钮状态
if size(judge,1) == 2
h(judge(1,2),judge(1,1)).Value = 0;
h(judge(2,2),judge(2,1)).Value = 0;
judge = [];
end
% 如果按下且不是重复点击则存入if h(i,j).Value && (size(judge,1) == 0 || (size(judge,1) == 1 && ~(judge(1,1) == j && judge(1,2) == i)))
judge = [judge;j,i,str2double(h(i,j).String)];% 注意行列顺序
% 若取消已存入按钮则取消
elseif ~h(i,j).Value && (size(judge,1) == 1 && ~(judge(1,1) == j && judge(1,2) == i))
h(judge(1,2),judge(1,1)).Value = 0;
judge = [];
end
% 如果已经按了2个按钮
if size(judge,1) == 2
% 坐标变换
judge(:,1) = 12 - judge(:,1);
judge(:,2) = judge(:,2) + 1;
flag = 0;
if judge(1,3) == judge(2,3)
M(judge(1,1),judge(1,2)) = 0;
M(judge(2,1),judge(2,2)) = 0;
for k = 1:12
%垂直判断
if sum(M(min([k,judge(1,1)]):max([k,judge(1,1)]),judge(1,2))) + ...
sum(M(k,min([judge(1,2),judge(2,2)]):max([judge(1,2),judge(2,2)]))) + ...
sum(M(min([k,judge(2,1)]):max([k,judge(2,1)]),judge(2,2))) == 0
flag = 1;
break;
end
%水平判断
if sum(M(judge(1,1),min([k,judge(1,2)]):max([k,judge(1,2)]))) + ...
sum(M(min([judge(1,1),judge(2,1)]):max([judge(1,1),judge(2,1)]),k)) + ...
sum(M(judge(2,1),min([k,judge(2,2)]):max([k,judge(2,2)]))) == 0
flag = 1;
break;
end
end
end
% 若不消除,Map恢复
if flag == 0
M(judge(1,1),judge(1,2)) = 1;
M(judge(2,1),judge(2,2)) = 1;
end
% 坐标反变换
judge(:,1) = 12 - judge(:,1);
judge(:,2) = judge(:,2) - 1;
% 若消除,隐藏按钮
if flag == 1
h(judge(1,2),judge(1,1)).Visible = 'off';
h(judge(2,2),judge(2,1)).Visible = 'off';
end
end
end
运行结果
实验难度总体不大,有些细节需注意如按钮坐标系和Matlab矩阵坐标系不同需要转换,单个双击自消等小bug。Matlab默认可以显示点中多个按钮,但考虑到连连看本身是两两匹配的,所以修改成同时只能选中两个按钮。此外,写垂直和水平判断时需细心,比较容易出错。