MATLAB編寫掃雷小遊戲

編寫程序在架構上參考了博主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

五、運行結果

       將程序分別放置在六個腳本之後,運行程序,調試成功。

失敗後必須關閉重新運行。鑑於成功的忘記截圖,所以不在展示。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章