zl程序教程

您现在的位置是:首页 >  后端

当前栏目

matlab 手把手教你制作五子棋小游戏

MATLAB 制作 手把手 小游戏 五子棋
2023-09-11 14:20:29 时间

想把以前写过的小游戏出一款详细教程呀
这两天发现五子棋有个简单的写法
虽然说有点弊端但这个程序真的很简单呀
一共只有70多行
相信大家就算没有基础多查多看也能学会吧嗯哒
第一步:界面设置
axis equal%让横竖坐标比例相等
axis([-10,10,-10,10])%坐标轴范围设置为X,Y轴都是-10到10
set(gca,‘xtick’,[],‘ytick’,[],‘xcolor’,‘w’,‘ycolor’,‘w’)
%用xtick,ytick删除掉坐标轴刻度,并将坐标轴颜色设置为white
set(gca,‘color’,[0.8392,0.7216,0.3804])
%将背景的颜色设置为棕色,这里的三个数字表示的是红蓝绿的比例
hold on%保持界面不关闭
第二步:绘制棋盘
这里直接用散点图scatter和折线图plot 进行绘制,直接暴力取点绘制
x1=[-9,-9,-8,-8,-7,-7,-6,-6,-5,-5,-4,-4,-3,-3,-2,-2,-1,-1,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9];
y1=[-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9];
x2=[-9,9,9,-9,-9];y2=[9,9,-9,-9,9];x3=[-9.2,9.2,9.2,-9.2,-9.2];y3=[9.2,9.2,-9.2,-9.2,9.2];x4=[-6,-6,-6,0,0,0,6,6,6];y4=[6,0,-6,6,0,-6,6,0,-6];
plot(x1,y1,‘k’)
plot(y1,x1,‘k’)
plot(x2,y2,‘k’,‘LineWidth’,2)
plot(x3,y3,‘k’)
scatter(gca,x4,y4,30,‘k’,‘filled’)
在这里插入图片描述
第三步:基础设置
row=19;col=19;%棋盘矩阵大小为19x19这里的矩阵大小画图使用不到的但是后期运算可以用到;
win=0;%这是判断输赢的一个参数
control=1;%这是判断下子颜色的一个参数,1为黑子,0为白子
postion=[0 0];%这是那个红叉的坐标就是下棋位置,这里的下棋方法为上下左右加空格键下棋
black=[20,20];white=[-20,-20];%随便取两个棋子的初始坐标
black(1,:)=[];white(1,:)=[];%把那两个初始坐标删掉
%这里取初始坐标又删掉是为了使这两个点集是两列的空矩阵
plotblack=scatter(gca,black(:,1),black(:,2),150,‘k’,‘filled’);
plotwhite=scatter(gca,white(:,1),white(:,2),150,‘w’,‘filled’);
plotpostion=scatter(gca,postion(1,1),postion(1,2),150,‘rx’);
设置绘图的初始数据
第四步:按键设置

set(gcf, 'KeyPressFcn', @key) %设置有任何按键动作时,调用key这个函数
    function key(~,event)%定义函数key,其中event是按键动作
        switch event.Key%将按键动作转换
            case 'uparrow'%上下左右这四个都是一样的这里只挑一个进行解释
            %将按键 uparrow即上箭头,转化为将postion坐标上移
                postion=postion+[0,1];
            case 'downarrow'
                postion=postion+[0,-1];
            case 'leftarrow'
                postion=postion+[-1,0];
            case 'rightarrow'
                postion=postion+[1,0];   
            case 'c'%将按键c转化为按下按键红叉回到画面最中央
                postion=[0,0];
            case 'space'%空格键
                if sum(ismember([black(:,1:2);white(:,1:2)],postion(1,1:2),'rows'))==0
                %这句话用来判断下棋的点上有没有棋子
                %这里解释一下
                %这个小程序里棋子的坐标储存方法是这样的
                %例如black=[x1,y1;x2,y2]就是指在(x1,y1),(x2,y2)坐标上两个点是黑棋
                %其他的白棋和红叉同理
                %然后解释一下ismember就是判断前面的集合的项在后面的集合中存不存在
                %因为我们每行代表一个点,我们这里加上‘rows'表示判断前面的点在后面存不存在
                %用法ismember(A,B,'rows')
                %当然也可以用效果差不多的intersect来判断
                %这里用sum有一点使懒,算是一种小bug的写法,最好还是用isempty判断
                    if control==1,black=[black;postion];end%如果control=1那么在红叉位置下黑子
                    if control==0,white=[white;postion];end%同上
                    control=mod(control+1,2);%mod是求余函数呀这里就是求control+1除以2的余数
                    %这样的话control就能1 0 1 0 1 0 的周期性变化啦,也就是轮流下黑子白子 
                end
            case 'backspace'
                co=0;
                if control==0&&~isempty(black),black(end,:)=[];co=1;end
                if control==1&&~isempty(white),white(end,:)=[];co=1;end
                if co==1,control=mod(control+1,2);end
        end
        wuziqigame()每次按完键后重新画一遍图,这里wuziqigame负责画图和显示输赢
        end

第五步:不断重新绘制棋盘

    function wuziqigame(~,~)
        postion(postion>9)=-9;%如果红叉坐标太大即超出界面,我们将它坐标减小移回界面内
        postion(postion<-9)=9;%和上面差不多
        panding()%这是一个胜负判断程序,后面会讲 
        set(plotblack,'XData',black(:,1),'YData',black(:,2))%还好scatter有Data功能,即可以不用删除上一幅图更新新的图片,非常好用
        set(plotwhite,'XData',white(:,1),'YData',white(:,2))
        set(plotpostion,'XData',postion(1,1),'YData',postion(1,2))
           if win==1%这个是一方赢事弹出窗口的程序,比较简单就不讲了
                buttonName1=questdlg('black win. What do you mean to do?','black win','close','restart','close');
                if isempty(buttonName1)
                    buttonName1='end'
                end
                if strcmp(buttonName1,'restart')
                    clf
                    wuziqi()
                else if strcmp(buttonName1,'close'),
                        close
                     end
                end
            end
            if win==-1
                buttonName1=questdlg('white win. What do you mean to do?','white win','close','restart','close');
                if isempty(buttonName1)
                    buttonName1='end'
                end
                if strcmp(buttonName1,'restart')
                    clf
                    wuziqi()
                else if strcmp(buttonName1,'close')
                        close
                    end
                end
            end
    end

第六步:判断输赢的核心算法
核心算法真的短的吓人呀
不过感觉可能不是很好理解
至少要能熟练地运用
这样写很简单还有一个写法就是相对于最后下的一步棋(因为形成的五子连珠必定是由于新棋子的加入,不然它在下新子之前就已经赢了)进行的链式搜索,可以以后再讲。

    function panding(~,~)
        mat=zeros(row+4,col+4);%创建一个比棋盘大四行四列的全零矩阵
        x=3:(row+2);y=3:(col+2);%设置x,y是中间row行col列
        qipan=zeros(row,col);%设置棋盘是row行col列的全零矩阵
        blackpos=black(:,1)+10+(black(:,2)+10-1)*row;
        whitepos=white(:,1)+10+(white(:,2)+10-1)*row;
        %将双参数索引转化为单参数索引
        %例如对19X19的矩阵来说它的第(1,2)个数,即第一行第二列对应其第20个数
        %这里加上10是因为棋子的坐标是从-9开始的
        qipan(blackpos)=1;%棋盘矩阵中黑子的位置设置数值为1
        qipan(whitepos)=-1;%棋盘矩阵中黑子的位置设置数值为-1
        mat(x,y)=qipan;%将棋盘矩阵放在比棋盘矩阵大两圈的矩阵的正中间
        mat1=mat(x,y)+mat(x+1,y)+mat(x+2,y)+mat(x-1,y)+mat(x-2,y);
        %每一个位置的数值和它左侧坐标,左左侧坐标,右侧坐标,右右侧坐标相加
        mat2=mat(x,y)+mat(x,y+1)+mat(x,y+2)+mat(x,y-1)+mat(x,y-2);
        %每一个位置的数值和它上侧坐标,上上侧坐标,下侧坐标,下下侧坐标相加
        mat3=mat(x,y)+mat(x+1,y+1)+mat(x+2,y+2)+mat(x-1,y-1)+mat(x-2,y-2);%与前面类似
        mat4=mat(x,y)+mat(x+1,y-1)+mat(x+2,y-2)+mat(x-1,y+1)+mat(x-2,y+2);
        con=[mat1;mat2;mat3;mat4];con1=con==5;con2=con==-5;%判断mat1到mat4中有没有数值为5或者负五的点
        if (sum(sum(con1)))~=0,win=1;end%如果有值为5的点黑色赢 
        if (sum(sum(con2)))~=0,win=-1;end%如果有值为-5的点白色赢       
    end

第七部:将各部分连接在一起
完整代码
这里因为代码太长会在手机上显示不全,所以分成了两个代码片
将其复制在同一个m文件就可以用啦

function wuziqi
    axis equal
    axis([-10,10,-10,10])
    set(gca,'xtick',[],'ytick',[],'xcolor','w','ycolor','w')
    set(gca,'color',[0.8392,0.7216,0.3804])
    hold on
    row=19;col=19;
    x1=[-9,-9,-8,-8,-7,-7,-6,-6,-5,-5,-4,-4,-3,-3,-2,-2,-1,-1,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9];
    y1=[-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9,9,-9,-9,9];
    x2=[-9,9,9,-9,-9];y2=[9,9,-9,-9,9];x3=[-9.2,9.2,9.2,-9.2,-9.2];y3=[9.2,9.2,-9.2,-9.2,9.2];x4=[-6,-6,-6,0,0,0,6,6,6];y4=[6,0,-6,6,0,-6,6,0,-6];
    plot(x1,y1,'k'),plot(y1,x1,'k'),plot(x2,y2,'k','LineWidth',2),plot(x3,y3,'k'),scatter(gca,x4,y4,30,'k','filled')
    win=0;control=1;postion=[0 0];
    black=[20,20];white=[-20,-20];
    black(1,:)=[];white(1,:)=[];
    plotblack=scatter(gca,black(:,1),black(:,2),150,'k','filled');
    plotwhite=scatter(gca,white(:,1),white(:,2),150,'w','filled');
    plotpostion=scatter(gca,postion(1,1),postion(1,2),150,'rx');
    set(gcf, 'KeyPressFcn', @key)  
    function wuziqigame(~,~)
        postion(postion>9)=-9;
        postion(postion<-9)=9;
        panding()
        set(plotblack,'XData',black(:,1),'YData',black(:,2))
        set(plotwhite,'XData',white(:,1),'YData',white(:,2))
        set(plotpostion,'XData',postion(1,1),'YData',postion(1,2))
           if win==1
                buttonName1=questdlg('black win. What do you mean to do?','black win','close','restart','close');
                if isempty(buttonName1),buttonName1='end';end
                if strcmp(buttonName1,'restart'),clf;wuziqi();
                else if strcmp(buttonName1,'close'),close;end
                end
            end
            if win==-1
                buttonName1=questdlg('white win. What do you mean to do?','white win','close','restart','close');
                if isempty(buttonName1),buttonName1='end';end
                if strcmp(buttonName1,'restart'),clf;wuziqi();
                else if strcmp(buttonName1,'close'),close;end
                end
            end
    end
    function panding(~,~)
        mat=zeros(row+4,col+4);
        x=3:(row+2);y=3:(col+2);
        qipan=zeros(row,col);
        blackpos=black(:,1)+10+(black(:,2)+10-1)*row;
        whitepos=white(:,1)+10+(white(:,2)+10-1)*row;
        qipan(blackpos)=1;qipan(whitepos)=-1;mat(x,y)=qipan;
        mat1=mat(x,y)+mat(x+1,y)+mat(x+2,y)+mat(x-1,y)+mat(x-2,y);
        mat2=mat(x,y)+mat(x,y+1)+mat(x,y+2)+mat(x,y-1)+mat(x,y-2);
        mat3=mat(x,y)+mat(x+1,y+1)+mat(x+2,y+2)+mat(x-1,y-1)+mat(x-2,y-2);
        mat4=mat(x,y)+mat(x+1,y-1)+mat(x+2,y-2)+mat(x-1,y+1)+mat(x-2,y+2);
        con=[mat1;mat2;mat3;mat4];con1=con==5;con2=con==-5;
        if (sum(sum(con1)))~=0,win=1;end
        if (sum(sum(con2)))~=0,win=-1;end      
    end
    function key(~,event)
        switch event.Key
            case 'uparrow',postion=postion+[0,1];
            case 'downarrow',postion=postion+[0,-1];
            case 'leftarrow',postion=postion+[-1,0];
            case 'rightarrow',postion=postion+[1,0];   
            case 'c',postion=[0,0];
            case 'space'
                if sum(ismember([black(:,1:2);white(:,1:2)],postion(1,1:2),'rows'))==0
                    if control==1,black=[black;postion];end
                    if control==0,white=[white;postion];end
                    control=mod(control+1,2);
                end
            case 'backspace'
                co=0;
                if control==0&&~isempty(black),black(end,:)=[];co=1;end
                if control==1&&~isempty(white),white(end,:)=[];co=1;end
                if co==1,control=mod(control+1,2);end
        end
        wuziqigame()
        end
end

在这里插入图片描述