編寫程序在架構上參考了博主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
五、運行結果
將程序分別放置在六個腳本之後,運行程序,調試成功。
失敗後必須關閉重新運行。鑑於成功的忘記截圖,所以不在展示。