编写程序在架构上参考了博主slandarer的文章matlab扫雷小游戏
一、构建棋盘
首先在matlab中构建一个新的脚本文件,建立一个figure,可以简单的添加目录标题美化视图,可以用循环输出按钮的方式建立一个长20格,宽15格的扫雷棋盘。代码如下
clear
global row col mines times number visit h flag F success f
f=0;
row=15;col=20;mines=45;
total=mines;times=1;
remine=row*col;
flag=0;
hf=figure('NumberTitle','off','Name','扫雷','menubar','none','position',[370,130,600,500]);
uh1=uimenu('label','帮助');
uimenu(uh1,'label','游戏规则','callback',['msgbox(''和windows自带的扫雷一个样,嗯哒'')'])
colormap([1 0 0;0 0 0;.65 .65 .65;1 1 1]);
axis off
hold on;
C=uicontrol(gcf,'style','text','unit','normalized',...
'position',[0.45,0.86,0.09,0.078],'fontsize',17,...
'BackgroundColor',0.85*[1 1 1],...
'string','o');
H=uicontrol(gcf,'style','text','unit','normalized',...
'position',[0.58,0.86,0.3,0.078],'fontsize',12,...
'BackgroundColor',0.85*[1 1 1],...
'string',['total:' num2str(total)]);
F=uicontrol(gcf,'style','text','unit','normalized',...
'position',[0.1,0.86,0.3,0.078],'fontsize',12,...
'BackgroundColor',0.85*[1 1 1],...
'string',['flag:' num2str(flag)]);
for m=1:row
for n=1:col
h(m,n)=uicontrol(gcf,'style','push',...
'foregroundColor',0.7*[1 1 1],...
'BackgroundColor',0.7*[1 1 1],...
'fontsize',15,'fontname','time new roman',...
'Unit','normalized','position',[0.013+0.045*n,0.86-0.054*m,0.043,0.052],...
'Visible','on',...
'callback',@pushcallback,'ButtonDownFcn',@buttoncallback);
end
end
二、初始化
建立棋盘后,对棋盘进行初始化,新建一个脚本,对棋盘所对应的数列进行初始化。并且在游戏一开始对棋盘进行布雷,布雷采用随机数的方式,并且点击的第一次不能为雷,而且布雷不能超过规定的范围。同时,如果点开的按钮不是雷,则会显示周边八个格的雷的总数。对二维数组进行赋值,若是雷则为-1,不是雷则是周边雷的数量。代码如下
function first_time(x,y)
global row col mines times number visit success
number=zeros(row,col);
visit=zeros(row,col);
cnt=0;
while cnt<mines
hang=round(rand*row);
lie=round(rand*col);
if hang==0 || lie==0
continue;
end
if hang==x && lie==y
continue
end
if number(hang,lie)==-1
continue;
end
number(hang,lie)=-1;
cnt=cnt+1;
end
success=number;
for i=1:row
for j=1:col
if number(i,j)==-1
continue;
end
% 左上
if i-1>=1 && j-1>=1 && number(i-1,j-1)==-1
number(i,j)=number(i,j)+1;
end
% 上
if i-1>=1 && j>=1 && number(i-1,j)==-1
number(i,j)=number(i,j)+1;
end
% 右上
if i-1>=1 && j+1<=col && number(i-1,j+1)==-1
number(i,j)=number(i,j)+1;
end
% 左
if j-1>=1 && number(i,j-1)==-1
number(i,j)=number(i,j)+1;
end
% 右
if j+1<=col && number(i,j+1)==-1
number(i,j)=number(i,j)+1;
end
% 左下
if i+1<=row && j-1>=1 && number(i+1,j-1)==-1
number(i,j)=number(i,j)+1;
end
% 下
if i+1<=row && j>=1 && number(i+1,j)==-1
number(i,j)=number(i,j)+1;
end
% 右下
if i+1<=row && j+1<=col && number(i+1,j+1)==-1
number(i,j)=number(i,j)+1;
end
end
end
end
三、左键函数
建立一个新的脚本,设定左键点击的回调函数,第一次左键点击时,对棋盘进行初始化以及布雷。每当点击按钮,若不是雷则显示数字,是雷则显示游戏结束,若该按钮为零,则要显示上下左右相邻的按钮也是空的量,知道出现一个不为零的数为止,不显示雷的按钮,设置标志位visit,用来判断按钮是否已经被遍历。采取dfs算法。代码如下
function pushcallback(hobject,~)
global row col mines times number visit h f
if f==1
msgbox('game over', '');
return;
end
a = get(hobject,'position');
hang=double((a(2)-0.86)/(-0.054))-0.0001;
lie=double((a(1)-0.013)/0.045)-0.0001;
hang = ceil(hang);
lie = ceil(lie);
% place=ceil([hang,lie]);
if times==1
first_time(hang,lie)
times=0;
end
if number(hang,lie)==-1
f=1;
msgbox('game over', '');
end
if number(hang,lie)>0
visit(hang,lie)=1;
set(h(hang,lie),'style','text','string',num2str(number(hang,lie)),'ForegroundColor','k','backgroundcolor',0.85*[1,1,1]);
end
if number(hang,lie)==0
dfs(hang,lie);
end
end
function dfs(i,j)
global row col mines times number visit h
if i<1 || i>row || j<1 || j>col
return;
end
if visit(i,j)==1
return;
end
visit(i,j)=1;
if number(i,j)>0
set(h(i,j),'style','text','string',num2str(number(i,j)),'ForegroundColor','k','backgroundcolor',0.85*[1,1,1]);
return;
end
if number(i,j)==-1
return;
end
set(h(i,j),'style','text','string',' ','ForegroundColor','k','backgroundcolor',0.85*[1,1,1]);
dfs(i-1,j);
dfs(i+1,j);
dfs(i,j+1);
dfs(i,j-1);
end
四、右键函数
在扫雷游戏中,右键表示标识雷的位置,所以,右键点击按钮,会出现 “ !” ,右键标有 “ !” 的按钮,则“ !”会消失,按钮可以重新进行操作。在标记雷时,flag会随着标记的数量改变。每当flag的数量与雷的数量相同时,会判断是否胜利,若胜利则显示游戏胜出,不胜利则可以继续操作。代码如下
function buttoncallback(hobject,~)
global row col mines times number visit h flag F success
a = get(hobject,'position');
hang=double((a(2)-0.86)/(-0.054))-0.0001;
lie=double((a(1)-0.013)/0.045)-0.0001;
hang = ceil(hang);
lie = ceil(lie);
if strcmp(get(gcf,'SelectionType'),'alt')
if ~strcmp(get(hobject,'style'),'text')
if ~strcmp(get(hobject,'string'),'!')
set(hobject,'string','!','ForegroundColor',[0.9,0,0])
flag=flag+1
set(F,'string',['flag:' num2str(flag)]);
success(hang,lie)=success(hang,lie)+1;
if flag==45
check()
end
else
set(hobject,'string',' ');
success(hang,lie)=success(hang,lie)-1;
flag=flag-1;set(F,'string',['flag:' num2str(flag)])
end
end
end
end
function check
global success
if all(success(:)==0)
msgbox('game success', '');
end
end
五、运行结果
将程序分别放置在六个脚本之后,运行程序,调试成功。
失败后必须关闭重新运行。鉴于成功的忘记截图,所以不在展示。