摘要:
使用matlab写的一款扫雷游戏,格子使用axes上的网格表示。
方向键可以改变当前位置,按"="键或者"end"键相当于windows
下的双击作用,按空格键标记雷的位置。
程序未经仔细调试还存在一些bug。
程序如下:
主程序:
% 扫雷 mine sweeping
close all;clc;clear;
M=16; % 行数
N=16; % 列数
NL=40; % 雷的总数
axes('Position',[0.2,0.1,0.6,0.8]);
% \copyright: zjliu
% Author's email: zjliu2001@163.com
set(gcf,'DoubleBuffer','on');
set(gca,'YDir','reverse');
hold on;
for m=0:M;
plot([0.5+m,0.5+m],[0.5,N+0.5],'k');
end
for n=0:N;
plot([0.5,0.5+M],[0.5+n,n+0.5],'k');
end
rr=randperm(M*N);
Zk=zeros(M,N);
Zk(rr(1:NL))=1;
Nu=zeros(M,N);
dm=[-1,-1,-1,0,0,1,1,1];
dn=[-1,0,1,-1,1,-1,0,1];
for m=1:M;
for n=1:N;
if Zk(m,n)==0;
for k=1:8;
mt=m+dm(k);
nt=n+dn(k);
if mt>=1&mt<=M&nt>=1&nt<=N;
Nu(m,n)=Nu(m,n)+Zk(mt,nt);
end
end
end
end
end
mt=8;nt=8;
ha=plot(mt,nt,'s','markersize',10);
Sw=zeros(M,N);
ht=title(['坐标: (',num2str(mt),',',num2str(nt),')']);
Yk=ylabel({'剩余','雷数',num2str(sum(Zk(:)))},...
'fontsize',16,'rotation',0,'color','r');
set(gcf,'KeyPressFcn',['K=get(gcf,''CurrentKey'');',...
'if K(1)==117;nt=nt-1;if nt>0.5&nt<N+0.5;',...
'set(ha,''Xdata'',mt,''YData'',nt);else nt=nt+1;end;end;',...
'if K(1)==100;nt=nt+1;if nt>0.5&nt<N+0.5;',...
'set(ha,''Xdata'',mt,''YData'',nt);else nt=nt-1;end;end;',...
'if K(1)==108;mt=mt-1;if mt>0.5&mt<M+0.5;',...
'set(ha,''Xdata'',mt,''YData'',nt);else mt=mt+1;end;end;',...
'if K(1)==114;mt=mt+1;if mt>0.5&mt<M+0.5;',...
'set(ha,''Xdata'',mt,''YData'',nt);else mt=mt-1;end;end;',...
'set(ht,''string'',[''坐标: ('',num2str(mt),'','',num2str(nt),'')'']);',...
'if K(1)==115;plot(mt,nt,''r.'',''markersize'',20,''EraseMode'',''xor'');',...
'Sw(mt,nt)=~Sw(mt,nt);Zk(mt,nt)=~Zk(mt,nt);end;',...
'if K(1)==101;if Zk(mt,nt)==1;title(''游戏结束,按p键重新开始'');',...
'set(gcf,''KeyPressFcn'',''K=get(gcf,''''CurrentKey'''');if K(1)==112;sweep_mine;end;'');',...
'plot(mt,nt,''r.'',''markersize'',24,''EraseMode'',''xor'');for m=1:M;for n=1:N;',...
'if Zk(m,n)>0.5;plot(m,n,''b.'',''markersize'',20);end;end;end;else ',...
'[mm,nn]=looks(mt,nt,M,N,Zk);for k=1:length(mm);',...
'text(mm(k)-0.2,nn(k),num2str(Nu(mm(k),nn(k))));end;end;end;',...
'if K(1)==119;for m=1:M;for n=1:N;if Zk(m,n)==1;',...
'plot(m,n,''r.'',''markersize'',20,''EraseMode'',''xor'');end;end;end;',...
'for m=1:M;for n=1:N;text(m-0.2,n,num2str(Nu(m,n)));end;end;end;',...
'if sum(sum(abs(Zk-Sw)))==0;title(''你成功了'');',...
'set(gcf,''CurrentKey'',[]);end;',...
'set(Yk,''string'',{''剩余'',''雷数'',num2str(sum(Zk(:)))});']);
探雷函数[请另存为looks.m文件]:
function [mm,nn]=looks(mt,nt,M,N,Zk);
% 返回左键探雷结果:点击鼠标左键于未知区域,如果未知区域有雷,
% 游戏停止,显示所有的地雷。如果没雷,则显示周围雷数,如果周围没雷,
% 则再查看周围八个区域是否有雷直到有雷为止并显示,这其实是一个递归过程。
%
mm=mt;nn=nt;m0=mt;n0=nt;
[mm,nn]=lookssss(mt,nt,M,N,Zk,mm,nn,m0,n0);
function [mm,nn]=lookssss(mt,nt,M,N,Zk,mm,nn,m0,n0);
dm=[-1,-1,-1,0,0,1,1,1];
dn=[-1,0,1,-1,1,-1,0,1];
mtn=mt+dm;ntn=nt+dn;
ntn(mtn<0.5|mtn>M+0.5)=[];
mtn(mtn<0.5|mtn>M+0.5)=[];
mtn(ntn<0.5|ntn>N+0.5)=[];
ntn(ntn<0.5|ntn>N+0.5)=[];
Sn=sub2ind([M,N],mtn,ntn);
L=abs((mt-m0)+(nt-n0)*i);
if sum(Zk(Sn))<0.5 & length(Sn)>3;
mm=[mm,mtn];nn=[nn,ntn];
for k=1:length(ntn);
Lt=abs((mtn(k)-m0)+(ntn-n0)*i);
if Lt>L;
[mm,nn]=lookssss(mtn(k),ntn(k),M,N,Zk,mm,nn,m0,n0);
end
end
end

