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

五、运行结果

       将程序分别放置在六个脚本之后,运行程序,调试成功。

失败后必须关闭重新运行。鉴于成功的忘记截图,所以不在展示。

 

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