zl程序教程

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

当前栏目

MATLAB 棋类小游戏合集(围棋,六子棋,走四棋,九子棋,含禁手五子棋等等)

MATLAB 合集 小游戏 等等 五子棋
2023-09-11 14:20:28 时间


由于文章较长,↑↑↑点击目录快速移动到想看的部分↑↑↑(好像只有电脑版csdn才能快速定位)

1 前言

用一个框架写了不少棋类小游戏(其中包含一个我自创的四子棋小游戏),初学者可以学习体会一下各个程序之间相似的结构和其中的不同,写了新的棋类游戏的话我也会在这里收录。


2 棋类合集

2.1 围棋

简介:
游戏支持键盘下棋和鼠标下棋两种下棋方式

键盘下棋:

  1. ↑↓←→键移动棋子
  2. 空格键(space)下棋
  3. Backspace键悔棋
  4. 'r’键重新开始

鼠标下棋:

  1. 左键下棋
  2. 右键悔棋
  3. 左右键同时按下重新开始

围棋吃子的判定较为复杂,故需要三个m文件组成完整函数,目前还没写判定胜负和禁手模块,有待更新。

游戏效果:
在这里插入图片描述

完整代码:
m文件1:
go.m | (围棋程序的主体)

function go
    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
%按键函数初始化设置:
    set(gcf,'KeyPressFcn',@key,'tag','keyset')
    set(gcf,'WindowButtonDownFcn',@buttondown)
%全局变量:
global winner;
global turn;
global checher_board
global black;
global white;
global postion;
global plotblack;
global plotwhite;
global plotpostion;
global bout;
global warehouse;
init()
    function init(~,~)
        %初始化前清除原有图像:
        delete(findobj('tag','piece'));
        delete(findobj('tag','redcross'));
        delete(findobj('type','line'));
        delete(findobj('type','patch'));
        
        %棋盘绘制:
        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')
        
        %棋子棋盘数值初始化:
        winner=0;postion=[0 0];turn=1;
        black=[20,20 0];white=[-20,-20 0];
        black(1,:)=[];white(1,:)=[];
        checher_board=zeros(19,19);
        
        bout=1;
        warehouse{bout,1}=checher_board;
        warehouse{bout,2}=turn;
        warehouse{bout,3}=black;
        warehouse{bout,4}=white;
        
        %绘制函数初始化:
        plotblack=scatter(gca,black(:,1),black(:,2),150,'k','filled','tag','piece');
        plotwhite=scatter(gca,white(:,1),white(:,2),150,'w','filled','tag','piece');
        plotpostion=scatter(gca,postion(1,1),postion(1,2),150,'rx','tag','redcross');
    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 'space',set_piece();
            case 'backspace',undo();
            case 'r',init();
        end
        postion(postion>9)=-9;
        postion(postion<-9)=9;
        redraw()
    end

    function buttondown(~,~)
        xy=get(gca,'CurrentPoint');
        xp=xy(1,2);yp=xy(1,1);
        pos=[yp,xp];
        pos=round(pos);
        if all(abs(pos)<=9)
            postion=round(pos);
            if strcmp(get(gcf,'SelectionType'),'alt'),undo();end
            if strcmp(get(gcf,'SelectionType'),'open'),undo();end
            if strcmp(get(gcf,'SelectionType'),'normal'),set_piece();end
            if strcmp(get(gcf,'SelectionType'),'extend'),init();end
            redraw()
        end
    end

    function set_piece(~,~)
        if checher_board(postion(1)+10,postion(2)+10)==0
            switch turn
                case 1
                    checher_board(postion(1)+10,postion(2)+10)=1;
                    surrounded=weather_surrounded(checher_board,postion+[10 10]);
                    black=[black;[postion,surrounded]];                        
                case 0
                    checher_board(postion(1)+10,postion(2)+10)=-1;
                    surrounded=weather_surrounded(checher_board,postion+[10 10]);
                    white=[white;[postion,surrounded]];        
            end
            black=[black(:,1:2),weather_surrounded(checher_board,black(:,1:2)+[10 10])];
            white=[white(:,1:2),weather_surrounded(checher_board,white(:,1:2)+[10 10])];
            if ~isempty(intersect(postion+[0 1],[black(:,1:2);white(:,1:2)],'rows')),eat(postion+[0 1]);end
            if ~isempty(intersect(postion+[0 -1],[black(:,1:2);white(:,1:2)],'rows')),eat(postion+[0 -1]);end
            if ~isempty(intersect(postion+[1 0],[black(:,1:2);white(:,1:2)],'rows')),eat(postion+[1 0]);end
            if ~isempty(intersect(postion+[-1 0],[black(:,1:2);white(:,1:2)],'rows')),eat(postion+[-1 0]);end
            black=[black(:,1:2),weather_surrounded(checher_board,black(:,1:2)+[10 10])];
            white=[white(:,1:2),weather_surrounded(checher_board,white(:,1:2)+[10 10])];
            turn=mod(turn+1,2);
            bout=bout+1;
            warehouse{bout,1}=checher_board;
            warehouse{bout,2}=turn;
            warehouse{bout,3}=black;
            warehouse{bout,4}=white;
        end     
    end

    function eat(pos)
        switch 1
            case ~isempty(intersect(pos,black(:,1:2),'rows'))
                connection_area=get_connection_area(black(:,1:2),pos);
                [~,b,~]=intersect(black(:,1:2),connection_area,'rows');
                if all(black(b,3))
                    checher_board((black(b,1)+10)+((black(b,2)+10)-1).*19)=0;
                    black(b,:)=[];              
                end
            case ~isempty(intersect(pos,white(:,1:2),'rows'))
                connection_area=get_connection_area(white(:,1:2),pos);
                [~,w,~]=intersect(white(:,1:2),connection_area,'rows');
                if all(white(w,3))
                    checher_board((white(w,1)+10)+((white(w,2)+10)-1).*19)=0;
                    white(w,:)=[];              
                end
        end
    end

    function undo(~,~)
        if winner~=0
            winner=0;
            delete(findobj('tag','clues'));
            plotpostion=scatter(gca,postion(1,1),postion(1,2),150,'rx','tag','redcross');
            bout=bout-1;
            warehouse(end,:)=[];
            checher_board=warehouse{bout,1};
            turn=warehouse{bout,2};
            black=warehouse{bout,3};
            white=warehouse{bout,4};
        else
            if bout~=1
            bout=bout-1;
            warehouse(end,:)=[];
            checher_board=warehouse{bout,1};
            turn=warehouse{bout,2};
            black=warehouse{bout,3};
            white=warehouse{bout,4};
            end
        end
    end

    function redraw(~,~)
        set(plotblack,'XData',black(:,1),'YData',black(:,2))
        set(plotwhite,'XData',white(:,1),'YData',white(:,2))
        set(plotpostion,'XData',postion(:,1),'YData',postion(:,2))
    end

end

m文件2:
weather_surrounded.m | (判断当前位置周围是否有空位)

function boolean=weather_surrounded(mat,pos)
%to detect if the piece is surrounded
%the mat is a matrix composed of 1,0,-1
[m,n]=size(mat);
temp_mat=abs(mat);
new_mat=temp_mat+[ones(m,1),temp_mat(:,1:n-1)]...
                +[temp_mat(:,2:end),ones(m,1)]...
                +[ones(1,n);temp_mat(1:m-1,:)]...
                +[temp_mat(2:end,:);ones(1,n)];
boolean=new_mat(pos(:,1)+(pos(:,2)-1).*m)==5;
end

m文件3:
get_connection_area.m | (获取当前位置联通区域)

function list=get_connection_area(pos_list,pos)
%always add new numbers from partb to parta
A=pos;
B=pos_list;
progress=[A;A+ones(size(A,1),1)*[0 1];...
            A+ones(size(A,1),1)*[0 -1];...
            A+ones(size(A,1),1)*[1 0];...
            A+ones(size(A,1),1)*[-1 0]];
progress=unique(progress,'rows');
while ~isempty(intersect(progress,B,'rows'))
    [a,~,b]=intersect(progress,B,'rows');
    A=[A;a];
    A=unique(A,'rows');
    B(b,:)=[];
    progress=[A;A+ones(size(A,1),1)*[0 1];...
            A+ones(size(A,1),1)*[0 -1];...
            A+ones(size(A,1),1)*[1 0];...
            A+ones(size(A,1),1)*[-1 0]];
    progress=unique(progress,'rows');
end
list=A;
end

2.2 四子棋

简介:
我自创的一种棋,在特殊格子内下棋,先连成四子为胜,开局黑棋先手且有禁手限制。

目前游戏只支持键盘下棋:

  1. ↑↓←→键移动棋子
  2. 空格键(space)下棋

游戏效果:
在这里插入图片描述
在这里插入图片描述

完整代码:
connect_four.m | (四子棋程序的全部)

function connect_four
%图形界面初始化:
    h=figure('NumberTitle','off','Name','四子棋','menubar','none');
    uh1=uimenu('label','帮助');
    uimenu(uh1,'label','游戏规则','callback',@msg)
    uimenu(uh1,'label','按键设置','callback',@msg)   
    axis equal,axis([-4,4,-4,4])
    set(gca,'xtick',[],'ytick',[],'xcolor','w','ycolor','w')
    set(gca,'color',[0.9,0.8,0.5])
    hold on
%按钮设置:
    uicontrol('parent',h,...
    'style','pushbutton',...
    'string','重新开始',...
    'position',[30 360 80 30],...
    'backgroundcolor',[0.85 0.89 0.85],...
    'foregroundcolor','k',...
    'fontsize',12,...
    'callback',@init);
    uicontrol('parent',h,...
    'style','pushbutton',...
    'string','悔棋',...
    'position',[30 320 80 30],...
    'backgroundcolor',[0.85 0.89 0.85],...
    'foregroundcolor','k',...
    'fontsize',12,...
    'callback',@undo);
    uicontrol('parent',h,...
    'tag','turn',...
    'style','text',...
    'HorizontalAlignment','left',...
    'string',{' 提示:';'';' 黑棋落子'},...
    'position',[30 210 80 100],...
    'backgroundcolor',[0.96 0.96 0.96],...
    'foregroundcolor','k',...
    'fontsize',11);
%按键函数初始化设置:
    set(gcf,'KeyPressFcn',@key,'tag','keyset')
%全局变量:
global black;             %黑子在棋盘中位置
global white;             %白子在棋盘中位置
global postion;           %红叉在棋盘中位置
global forbid_pos;        %禁手位置
global avilable_pos;      %可下位置
global turn;              %下棋方,值为1时黑方下,值为0时白方下
global winner;            %胜方,值为1时黑棋胜,值为-1时白棋胜
global checherboard;      %7x7棋盘矩阵,值可能为0,1,-1
global plotblack;         %绘制黑子的函数
global plotwhite;         %绘制白子的函数
%global plotpostion;      %绘制红叉的函数
init()

    function init(~,~)
        %初始化函数
        %每次初始化前删除之前图像:
        delete(findobj('type','line'));
        delete(findobj('type','patch'));
        delete(findobj('tag','piece'));
        delete(findobj('tag','redcross'));
        
        %棋子棋盘数值初始化:
        black=[20,20];white=[20,20];postion=[0 0];
        winner=0;checherboard=zeros(7,7);turn=1;
        forbid_pos=[1 0;-1 0;0 1;0 -1;1 1;1 -1;-1 1;-1 -1;2 0;0 2;0 -2;-2 0];
        avilable_pos=[[(-2:1:2)',2*ones(5,1)];...
                      [(-2:1:2)',1*ones(5,1)];...
                      [(-2:1:2)',0*ones(5,1)];...
                      [(-2:1:2)',-1*ones(5,1)];...
                      [(-2:1:2)',-2*ones(5,1)];...
                      [1,3;3,1;3,-1;1,-3;-1,3;-3,1;-1,-3;-3,-1]];
        [~,d,~]=intersect(avilable_pos,forbid_pos,'rows');
        avilable_pos(d,:)=[];
        
        %用来绘制棋子红叉的函数初始化:
        plotblack=scatter(gca,black(:,1),black(:,2),420,'k','filled','tag','piece');
        plotwhite=scatter(gca,white(:,1),white(:,2),420,'w','filled','tag','piece');%plotpostion=scatter(gca,postion(1,1),postion(1,2),220,'rx');
        text(postion(1,1),postion(1,2),'x','color',[0.8 0 0],'fontsize',20,'HorizontalAlignment', 'center','tag','redcross');
        
        %绘制棋盘:
        x1=[-3.5,3.5,3.5,-3.5,-3.5];y1=[0.5,0.5,1.5,1.5,0.5];
        x2=[-2.5,2.5,2.5,-2.5,-2.5];y2=[1.5,1.5,2.5,2.5,1.5];
        y11=[-0.5,-0.5,-1.5,-1.5,-0.5];y22=[-1.5,-1.5,-2.5,-2.5,-1.5];
        plot(x1,y1,'k',x1,y11,'k',y1,x1,'k',y11,x1,'k')
        plot(x2,y2,'k',x2,y22,'k',y2,x2,'k',y22,x2,'k')
        edge=[1.5,3.5;3.5,1.5;3.5,-1.5;1.5,-3.5;-1.5,-3.5;-3.5,-1.5;-3.5,1.5;-1.5,3.5;1.5,3.5];
        plot(edge(:,1),edge(:,2),'color','k','linewidth',1)
        plot(edge(:,1).*1.05,edge(:,2).*1.05,'color','k','linewidth',1.2)
        
        %绘制禁手位置:
        shadow1=[0.5,0.5;1.5,0.5;1.5,-0.5;0.5,-0.5;0.5,0.5];
        fill(shadow1(:,1),shadow1(:,2),[0.9,0.8,0.5]*0.8,'tag','forbid')
        fill(shadow1(:,1).*(-1),shadow1(:,2),[0.9,0.8,0.5]*0.8,'tag','forbid')
        fill(shadow1(:,2),shadow1(:,1),[0.9,0.8,0.5]*0.8,'tag','forbid')
        fill(shadow1(:,2),shadow1(:,1).*(-1),[0.9,0.8,0.5]*0.8,'tag','forbid')
        shadow4=[0.5,0.5;0.5,1.5;1.5,1.5;1.5,0.5;0.5,0.5];
        fill(shadow4(:,1),shadow4(:,2),[0.9,0.8,0.5]*0.8,'tag','forbid')
        fill(shadow4(:,1).*(-1),shadow4(:,2),[0.9,0.8,0.5]*0.8,'tag','forbid')
        fill(shadow4(:,2),shadow4(:,1).*(-1),[0.9,0.8,0.5]*0.8,'tag','forbid')
        fill(shadow4(:,2).*(-1),shadow4(:,1).*(-1),[0.9,0.8,0.5]*0.8,'tag','forbid')
        shadow5=[1.5,-0.5;2.5,-0.5;2.5,0.5;1.5,0.5;1.5,-0.5];
        fill(shadow5(:,1),shadow5(:,2),[0.9,0.8,0.5]*0.8,'tag','forbid')
        fill(shadow5(:,1).*(-1),shadow5(:,2),[0.9,0.8,0.5]*0.8,'tag','forbid')
        fill(shadow5(:,2),shadow5(:,1),[0.9,0.8,0.5]*0.8,'tag','forbid')
        fill(shadow5(:,2).*(-1),shadow5(:,1).*(-1),[0.9,0.8,0.5]*0.8,'tag','forbid')
        
        shadow2=[2.5,1.5;3.5,1.5;2.5,2.5;2.5,1.5];
        fill(shadow2(:,1),shadow2(:,2),[0.9,0.8,0.5]*0.8)
        fill(shadow2(:,1).*(-1),shadow2(:,2),[0.9,0.8,0.5]*0.8)
        fill(shadow2(:,1),shadow2(:,2).*(-1),[0.9,0.8,0.5]*0.8)
        fill(shadow2(:,1).*(-1),shadow2(:,2).*(-1),[0.9,0.8,0.5]*0.8)
        fill(shadow2(:,2),shadow2(:,1),[0.9,0.8,0.5]*0.8)
        fill(shadow2(:,2).*(-1),shadow2(:,1),[0.9,0.8,0.5]*0.8)
        fill(shadow2(:,2),shadow2(:,1).*(-1),[0.9,0.8,0.5]*0.8)
        fill(shadow2(:,2).*(-1),shadow2(:,1).*(-1),[0.9,0.8,0.5]*0.8)
        shadow3=[2.5,-0.5;3.5,-0.5;3.5,0.5;2.5,0.5;2.5,-0.5];
        fill(shadow3(:,1),shadow3(:,2),[0.9,0.8,0.5]*0.8)
        fill(shadow3(:,1).*(-1),shadow3(:,2),[0.9,0.8,0.5]*0.8)
        fill(shadow3(:,2),shadow3(:,1),[0.9,0.8,0.5]*0.8)
        fill(shadow3(:,2),shadow3(:,1).*(-1),[0.9,0.8,0.5]*0.8)    
    end

    function msg(menuData,~)
        %提示文本弹出函数
            switch menuData.Text
                case '游戏规则',msgbox({'游戏规则:';'  在棋盘内落子,当横竖或斜着连成四子即为胜利 ';...
                                     '';'禁手规则:';'  第一步棋不能下在棋盘颜色较暗的格子内'});
                case '按键设置',msgbox({'按键设置:';'  1.↑↓←→改变落子位置';...
                                                    '  2.空格键落子'});
            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 'space'
                if checherboard(postion(1)+4,postion(2)+4)==0&&~isempty(intersect(postion,avilable_pos,'rows'))&&winner==0
                        switch turn
                            case 1,black=[black;postion];checherboard(postion(1)+4,postion(2)+4)=1;
                            case 0,white=[white;postion];checherboard(postion(1)+4,postion(2)+4)=-1;   
                        end
                        avilable_pos=[avilable_pos;forbid_pos];
                        avilable_pos=unique(avilable_pos,'rows');
                        turn=mod(turn+1,2);%值为1时下黑子,值为0时下白子
                end
        end
        %使红叉不超出棋盘范围:
        postion(postion>3)=-3;
        postion(postion<-3)=3;
        redraw()
    end

    function redraw(~,~)
        %图像更新函数
        %删除第一步的禁手限制:
        if any(any(checherboard~=0))
            delete(findobj('tag','forbid'));
        end
        %重新绘制图像: 
        delete(findobj('tag','redcross'));
        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))
        text(postion(1,1),postion(1,2),'x','color',[0.8 0 0],'fontsize',20,'HorizontalAlignment', 'center','tag','redcross');
        if winner==0
            switch turn
                case 1,set(findobj('tag','turn'),'string',{' 提示:';'';' 黑棋落子'});
                case 0,set(findobj('tag','turn'),'string',{' 提示:';'';' 白棋落子'});
            end
        else
            switch winner
                case 1,set(findobj('tag','turn'),'string',{' 提示:';'';' 黑棋获胜'});
                case -1,set(findobj('tag','turn'),'string',{' 提示:';'';' 白棋获胜'});
            end
        end
        judge()
    end

    function judge(~,~)
        temp_mat_1=checherboard+[checherboard(:,2:end),zeros(7,1)]+[checherboard(:,3:end),zeros(7,2)]+[checherboard(:,4:end),zeros(7,3)];%向上
        temp_mat_2=checherboard+[checherboard(2:end,:);zeros(1,7)]+[checherboard(3:end,:);zeros(2,7)]+[checherboard(4:end,:);zeros(3,7)];%向右
        temp_mat_3=checherboard+[zeros(1,7);[checherboard(1:6,2:end),zeros(6,1)]]+...
                                [zeros(2,7);[checherboard(1:5,3:end),zeros(5,2)]]+...
                                [zeros(3,7);[checherboard(1:4,4:end),zeros(4,3)]];%左上
        temp_mat_4=checherboard+[[checherboard(2:end,2:end),zeros(6,1)];zeros(1,7)]+...
                                [[checherboard(3:end,3:end),zeros(5,2)];zeros(2,7)]+...
                                [[checherboard(4:end,4:end),zeros(4,3)];zeros(3,7)];%右上
        switch 1
            case any(any(temp_mat_1==4))||any(any(temp_mat_1==-4)),winner=any(any(temp_mat_1==4))-any(any(temp_mat_1==-4));[pos_x,pos_y]=find(temp_mat_1(:,:)==winner*4);dir=1;
            case any(any(temp_mat_2==4))||any(any(temp_mat_2==-4)),winner=any(any(temp_mat_2==4))-any(any(temp_mat_2==-4));[pos_x,pos_y]=find(temp_mat_2(:,:)==winner*4);dir=2;
            case any(any(temp_mat_3==4))||any(any(temp_mat_3==-4)),winner=any(any(temp_mat_3==4))-any(any(temp_mat_3==-4));[pos_x,pos_y]=find(temp_mat_3(:,:)==winner*4);dir=3;
            case any(any(temp_mat_4==4))||any(any(temp_mat_4==-4)),winner=any(any(temp_mat_4==4))-any(any(temp_mat_4==-4));[pos_x,pos_y]=find(temp_mat_4(:,:)==winner*4);dir=4;
        end
        vector=[0 3;3 0;-3 3;3 3];
        if winner~=0
            plot([pos_x-4;pos_x-4+vector(dir,1)],[pos_y-4;pos_y-4+vector(dir,2)],'color',[0.8 0 0],'linewidth',2,'tag','clues')
            delete(findobj('tag','redcross'))
            switch winner
                case 1,set(findobj('tag','turn'),'string',{' 提示:';'';' 黑棋获胜'});
                case -1,set(findobj('tag','turn'),'string',{' 提示:';'';' 白棋获胜'});
            end
        end
        %输赢判定函数
    end

    function undo(~,~)
        if winner~=0
            delete(findobj('tag','clues'));      
        end
        if any(any(checherboard~=0))
            switch turn
                case 1,if ~isempty(white),checherboard(white(end,1)+4,white(end,2)+4)=0;white(end,:)=[];turn=0;end
                case 0,if ~isempty(black),checherboard(black(end,1)+4,black(end,2)+4)=0;black(end,:)=[];turn=1;end
            end
        end
        if ~any(any(checherboard~=0))
            init()
        end
        redraw()
    end

end

2.3 走四棋

简介:
网上找的介绍:
走四棋在乡下是一种全民性游戏,简单易行,老少皆宜。

玩法:在地上画一棋盘,纵横线各四条,每人执四个棋子(多用石块、砖块、木块等代替)对阵摆布。

走子时,纵横进退,但每次只许走一步。若一方两棋子相邻,且与对方的一棋子在同一条直线上,且线上再无别的棋子时,则“吃”掉对方一棋子。若一方只剩下一个棋子,无法对阵时为输。

只支持鼠标操作,鼠标点击棋子,会出现可走的位置,再点击可走位置即可移动棋子。

游戏效果:
在这里插入图片描述
注:绿圈的位置即为可行位置。
 绿圈处即为可走位置

完整代码:
move_four.m | (走四棋程序的全部)

function move_four
    axis equal
    axis([0.5,4.5,0.5,4.5])
    set(gca,'xtick',[],'ytick',[],'xcolor',[0.95 0.95 0.95],'ycolor',[0.95 0.95 0.95])
    set(gca,'color',[0.95 0.95 0.95])
    hold on
    %按键函数初始化设置:
    set(gcf,'WindowButtonDownFcn',@buttondown)
global red;
global blue;
global winner;
global turn;
global pos_arrivable;
global checher_board;
global postion;
global all_piece;
global plotred;
global plotblue;
global plotallpiece1;
global plotallpiece2;
global plotarrivable;
global plotpostion1;
global plotpostion2;
global nowaplace;
init()
    function init(~,~)
        delete(findobj('tag','piece'));
        delete(findobj('tag','select'));
        delete(findobj('type','line'));
        delete(findobj('type','patch'));
        
        l1=[1 1;1 4;4 4;4 1;1 1];
        l2=[1 2;4 2];
        plot(l1(:,1),l1(:,2),'color',[0 0 0],'linewidth',4);
        plot(l2(:,1),l2(:,2),'color',[0 0 0],'linewidth',4);
        plot(l2(:,2),l2(:,1),'color',[0 0 0],'linewidth',4);
        plot(l2(:,1),l2(:,2)+1,'color',[0 0 0],'linewidth',4);
        plot(l2(:,2)+1,l2(:,1),'color',[0 0 0],'linewidth',4);
        
        red=[1 1;1 2;1 3;1 4];
        blue=[4 1;4 2;4 3;4 4];
        all_piece=[red;blue];
        winner=0;turn=1;
        checher_board=zeros(4,4);
        checher_board(red(:,1)+(red(:,2)-1)*4)=1;
        checher_board(blue(:,1)+(blue(:,2)-1)*4)=-1;
        postion=[1 1];
        postion(1,:)=[];
        pos_arrivable=[1 1];
        pos_arrivable(1,:)=[];
        
        plotred=scatter(gca,red(:,1),red(:,2),1800,'k','filled','CData',[0.8157 0.4275 0.0588],'tag','piece');
        plotblue=scatter(gca,blue(:,1),blue(:,2),1800,'w','filled','CData',[0 0.5255 0.9255],'tag','piece');
        plotallpiece1=scatter(gca,all_piece(:,1),all_piece(:,2),1000,'CData',[0.75 0.75 0.75],'linewidth',1,'tag','piece');
        plotallpiece2=scatter(gca,all_piece(:,1),all_piece(:,2),1850,'CData',[0 0 0],'linewidth',1,'tag','piece');
        plotpostion1=scatter(gca,postion(:,1),postion(:,2),60,'s','filled','CData',[1.0000 1.0000 0.9843],'tag','select');
        plotpostion2=scatter(gca,postion(:,1),postion(:,2),60,'s','CData',[0.6627 0.8706 1.0000],'linewidth',2,'tag','select');
        plotarrivable=scatter(gca,pos_arrivable(:,1),pos_arrivable(:,2),100,'c','CData',[0.5373 0.9059 0.3255],'linewidth',4,'tag','gc');
    end

    function buttondown(~,~)
        xy=get(gca,'CurrentPoint');
        xp=xy(1,2);yp=xy(1,1);
        pos=[yp,xp];
        pos=round(pos);
        if all(1<=pos)&&all(pos<=4)&&winner==0
            postion=pos;
            switch 1
                case checher_board(postion(1),postion(2))==0&&isempty(intersect(postion,pos_arrivable,'rows'))
                    pos_arrivable(:,:)=[];
                case ~isempty(intersect(postion,red,'rows'))
                    switch turn
                        case 1,pos_arrivable=get_arrivable(postion);nowaplace=postion;
                        case 0,pos_arrivable(:,:)=[];
                    end
                case ~isempty(intersect(postion,blue,'rows'))
                    switch turn
                        case 1,pos_arrivable(:,:)=[];
                        case 0,pos_arrivable=get_arrivable(postion);nowaplace=postion;
                    end
                case ~isempty(intersect(postion,pos_arrivable,'rows'))
                    switch turn 
                        case 1
                            red(sum(abs(red-nowaplace),2)==0,:)=postion;
                            checher_board(nowaplace(1),nowaplace(2))=0;
                            checher_board(postion(1),postion(2))=1;   
                            delete_pos=eat(postion,turn);
                            if ~isempty(delete_pos)
                                [~,b,~]=intersect(blue,delete_pos,'rows');
                                blue(b,:)=[];
                                checher_board(delete_pos(1)+(delete_pos(2)-1).*4)=0;
                            end
                            all_piece=[red;blue];
                            turn=mod(turn+1,2);
                            pos_arrivable(:,:)=[];                      
                        case 0
                            blue(sum(abs(blue-nowaplace),2)==0,:)=postion;
                            checher_board(nowaplace(1),nowaplace(2))=0;
                            checher_board(postion(1),postion(2))=-1;
                            delete_pos=eat(postion,turn);
                            if ~isempty(delete_pos)
                                [~,b,~]=intersect(red,delete_pos,'rows');
                                red(b,:)=[];
                                checher_board(delete_pos(1)+(delete_pos(2)-1).*4)=0;
                            end
                            all_piece=[red;blue];
                            turn=mod(turn+1,2);
                            pos_arrivable(:,:)=[];
                    end
            end
        end
        redraw()
    end

    function arrivable_list=get_arrivable(pos)
        pos_around=[pos;pos+[1 0];pos+[0 1];pos+[-1 0];pos+[0 -1]];
        pos_around(pos_around(:,1)>4|pos_around(:,1)<1,:)=[];
        pos_around(pos_around(:,2)>4|pos_around(:,2)<1,:)=[];
        arrivable_list=pos_around(checher_board(pos_around(:,1)+(pos_around(:,2)-1).*4)==0,:);
    end

    function delete_pos=eat(pos,turn)
        switch turn
            case 0,turn=-1;
        end
        delete_pos1=[0 0];delete_pos1(1,:)=[];
        delete_pos2=[0 0];delete_pos2(1,:)=[];
        delete_pos3=[0 0];delete_pos3(1,:)=[];
        delete_pos4=[0 0];delete_pos4(1,:)=[];
        delete_pos5=[0 0];delete_pos5(1,:)=[];
        delete_pos6=[0 0];delete_pos6(1,:)=[];
        sums_this_row=sum(checher_board(pos(1),:)==-turn);
        sums_this_col=sum(checher_board(:,pos(2))==-turn);
        if pos(1)+2<=4
            if checher_board(pos(1)+1,pos(2))==turn&&...
               checher_board(pos(1)+2,pos(2))==-turn&&...
               sums_this_col==1
                delete_pos1=[pos(1)+2,pos(2)];
            end
        end
        if pos(1)-2>=1
            if checher_board(pos(1)-1,pos(2))==turn&&...
               checher_board(pos(1)-2,pos(2))==-turn&&...
               sums_this_col==1
                delete_pos2=[pos(1)-2,pos(2)];
            end
        end
        if pos(2)+2<=4
            if checher_board(pos(1),pos(2)+1)==turn&&...
               checher_board(pos(1),pos(2)+2)==-turn&&...
               sums_this_row==1
                delete_pos3=[pos(1),pos(2)+2];
            end
        end
        if pos(2)-2>=1
            if checher_board(pos(1),pos(2)-1)==turn&&...
               checher_board(pos(1),pos(2)-2)==-turn&&...
               sums_this_row==1
                delete_pos4=[pos(1),pos(2)-2];
            end
        end
        if pos(1)+1<=4&&pos(1)-1>=1
            if checher_board(pos(1)+1,pos(2))==turn&&...
               checher_board(pos(1)-1,pos(2))==-turn&&...
               sums_this_col==1
                delete_pos5=[pos(1)-1,pos(2)];
            end
            if checher_board(pos(1)+1,pos(2))==-turn&&...
               checher_board(pos(1)-1,pos(2))==turn&&...
               sums_this_col==1
                delete_pos5=[pos(1)+1,pos(2)];
            end  
        end
        if pos(2)+1<=4&&pos(2)-1>=1
            if checher_board(pos(1),pos(2)+1)==turn&&...
               checher_board(pos(1),pos(2)-1)==-turn&&...
               sums_this_row==1
                delete_pos6=[pos(1),pos(2)-1];
            end
            if checher_board(pos(1),pos(2)+1)==-turn&&...
               checher_board(pos(1),pos(2)-1)==turn&&...
               sums_this_row==1
                delete_pos6=[pos(1),pos(2)+1];
            end  
        end
        delete_pos=[delete_pos1;delete_pos2;delete_pos3;delete_pos4;delete_pos5;delete_pos6];
    end

    function redraw(~,~)
        set(plotred,'XData',red(:,1),'YData',red(:,2));
        set(plotblue,'XData',blue(:,1),'YData',blue(:,2));
        set(plotallpiece1,'XData',all_piece(:,1),'YData',all_piece(:,2));
        set(plotallpiece2,'XData',all_piece(:,1),'YData',all_piece(:,2));
        set(plotpostion1,'XData',postion(:,1),'YData',postion(1,2));
        set(plotpostion2,'XData',postion(:,1),'YData',postion(1,2));
        set(plotarrivable,'XData',pos_arrivable(:,1),'YData',pos_arrivable(:,2));
        judge()
    end

    function judge(~,~)
        switch 1
            case size(red,1)<=2,winner=-1;
            case size(blue,1)<=2,winner=1;
        end
        switch winner
            case 1
                buttonName1=questdlg('红方胜利','red win','关闭','重新开始','关闭');
                if isempty(buttonName1),buttonName1='end';end
                if strcmp(buttonName1,'重新开始'),init();
                elseif strcmp(buttonName1,'关闭'),close;
                end
            case -1
                buttonName1=questdlg('蓝方胜利','blue win','关闭','重新开始','关闭');
                if isempty(buttonName1),buttonName1='end';end
                if strcmp(buttonName1,'重新开始'),init();
                elseif strcmp(buttonName1,'关闭'),close;
                end
        end
    end


end

2.4 五子棋(含禁手)

简介:
游戏支持键盘下棋和鼠标下棋两种下棋方式

键盘下棋:

  1. ↑↓←→键移动棋子
  2. 空格键(space)下棋
  3. Backspace键悔棋
  4. 'r’键重新开始

鼠标下棋:

  1. 左键下棋
  2. 右键悔棋
  3. 左右键同时按下重新开始

禁手包括:

  1. 三三禁手
  2. 四四禁手
  3. 长联禁手

函数分为五个m文件

完整代码:
m文件1:
fiveinrow_with_forbid.m | (五子棋程序主要部分)

function fiveinrow_with_forbid
%图形界面初始化:
    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
%按键函数初始化设置:
    set(gcf,'KeyPressFcn',@key,'tag','keyset')
    set(gcf,'WindowButtonDownFcn',@buttondown)
%全局变量:
global winner;
global turn;
global checher_board
global black;
global white;
global postion;
global plotblack;
global plotwhite;
global plotpostion;

init()
    function init(~,~)
        %初始化前清除原有图像:
        delete(findobj('tag','piece'));
        delete(findobj('tag','redcross'));
        delete(findobj('type','line'));
        delete(findobj('type','patch'));
        
        %棋盘绘制:
        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')
        
        %棋子棋盘数值初始化:
        winner=0;postion=[0 0];turn=1;
        black=[20,20];white=[-20,-20];
        black(1,:)=[];white(1,:)=[];
        checher_board=zeros(19,19);
        
        %绘制函数初始化:
        plotblack=scatter(gca,black(:,1),black(:,2),150,'k','filled','tag','piece');
        plotwhite=scatter(gca,white(:,1),white(:,2),150,'w','filled','tag','piece');
        plotpostion=scatter(gca,postion(1,1),postion(1,2),150,'rx','tag','redcross');
    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 'space',set_piece();
            case 'backspace',undo();
            case 'r',init();
        end
        postion(postion>9)=-9;
        postion(postion<-9)=9;
        redraw()
    end

    function buttondown(~,~)
        xy=get(gca,'CurrentPoint');
        xp=xy(1,2);yp=xy(1,1);
        pos=[yp,xp];
        pos=round(pos);
        if all(abs(pos)<=9)
            postion=round(pos);
            if strcmp(get(gcf,'SelectionType'),'alt'),undo();end
            if strcmp(get(gcf,'SelectionType'),'open'),undo();end
            if strcmp(get(gcf,'SelectionType'),'normal'),set_piece();end
            if strcmp(get(gcf,'SelectionType'),'extend'),init();end
            redraw()
        end
    end

    function set_piece(~,~)
        if checher_board(postion(1)+10,postion(2)+10)==0&&winner==0
            switch turn
                case 1
                    if ~forbid(postion)
                        checher_board(postion(1)+10,postion(2)+10)=1;
                        black=[black;postion];
                        turn=mod(turn+1,2);
                    end
                case 0
                    checher_board(postion(1)+10,postion(2)+10)=-1;
                    white=[white;postion];
                    turn=mod(turn+1,2);
            end
            
        end     
    end

    function redraw(~,~)
        if winner==0
            set(plotblack,'XData',black(:,1),'YData',black(:,2))
            set(plotwhite,'XData',white(:,1),'YData',white(:,2))
            set(plotpostion,'XData',postion(:,1),'YData',postion(:,2))
        judge()
        end
    end

    function judge(~,~)
        temp_mat_1=checher_board+[zeros(19,1),checher_board(:,1:18)]...
                                +[zeros(19,2),checher_board(:,1:17)]...
                                +[checher_board(:,2:end),zeros(19,1)]...
                                +[checher_board(:,3:end),zeros(19,2)];
        temp_mat_2=checher_board+[zeros(1,19);checher_board(1:18,:)]...
                                +[zeros(2,19);checher_board(1:17,:)]...
                                +[checher_board(2:end,:);zeros(1,19)]...
                                +[checher_board(3:end,:);zeros(2,19)];
        temp_mat_3=checher_board+[zeros(1,19);[zeros(18,1),checher_board(1:18,1:18)]]...
                                +[zeros(2,19);[zeros(17,2),checher_board(1:17,1:17)]]...
                                +[[checher_board(2:end,2:end),zeros(18,1)];zeros(1,19)]...
                                +[[checher_board(3:end,3:end),zeros(17,2)];zeros(2,19)];
        temp_mat_4=checher_board+[[zeros(18,1),checher_board(2:end,1:18)];zeros(1,19)]...
                                +[[zeros(17,2),checher_board(3:end,1:17)];zeros(2,19)]...
                                +[zeros(1,19);[checher_board(1:18,2:end),zeros(18,1)]]...
                                +[zeros(2,19);[checher_board(1:17,3:end),zeros(17,2)]];
        switch 1
            case any(any(temp_mat_1==5))||any(any(temp_mat_1==-5)),winner=any(any(temp_mat_1==5))-any(any(temp_mat_1==-5));
                [pos_x,pos_y]=find(temp_mat_1(:,:)==winner*5);endpoint=[pos_x(1),pos_y(1);pos_x(1),pos_y(1)]+[0 2;0 -2];
            case any(any(temp_mat_2==5))||any(any(temp_mat_2==-5)),winner=any(any(temp_mat_2==5))-any(any(temp_mat_2==-5));
                [pos_x,pos_y]=find(temp_mat_2(:,:)==winner*5);endpoint=[pos_x(1),pos_y(1);pos_x(1),pos_y(1)]+[2 0;-2 0];
            case any(any(temp_mat_3==5))||any(any(temp_mat_3==-5)),winner=any(any(temp_mat_3==5))-any(any(temp_mat_3==-5));
                [pos_x,pos_y]=find(temp_mat_3(:,:)==winner*5);endpoint=[pos_x(1),pos_y(1);pos_x(1),pos_y(1)]+[2 2;-2 -2];
            case any(any(temp_mat_4==5))||any(any(temp_mat_4==-5)),winner=any(any(temp_mat_4==5))-any(any(temp_mat_4==-5));
                [pos_x,pos_y]=find(temp_mat_4(:,:)==winner*5);endpoint=[pos_x(1),pos_y(1);pos_x(1),pos_y(1)]+[2 -2;-2 2];
        end
        if winner~=0
            plot(endpoint(:,1)-10,endpoint(:,2)-10,'color',[0.8 0 0],'linewidth',2,'tag','clues')
            delete(findobj('tag','redcross'))
        end
    end

    function boolean=forbid(pos)
        boolean=0;
        if long_connect(black,pos)||double_four(black,checher_board,pos)||double_three(checher_board,pos)
                boolean=1;
        end     
    end
    
    function undo(~,~)
        if winner~=0
            winner=0;
            delete(findobj('tag','clues'));
            plotpostion=scatter(gca,postion(1,1),postion(1,2),150,'rx','tag','redcross');
        end
        if any(any(checher_board~=0))
            turn=mod(turn+1,2);
            switch turn
                case 1,checher_board(black(end,1)+10,black(end,2)+10)=0;black(end,:)=[];
                case 0,checher_board(white(end,1)+10,white(end,2)+10)=0;white(end,:)=[];
            end
            
        end
    end

end

m文件2:
get_connection_area2.m |(获取某一方向联通区域)

function list=get_connection_area2(pos_list,pos,dir)
%always add new numbers from partb to parta
switch dir
    case 1,dir=[0 1];
    case 2,dir=[1 0];
    case 3,dir=[1 1];
    case 4,dir=[1 -1];
end
A=pos;
B=pos_list;
progress=[A;A+ones(size(A,1),1)*dir;...
            A+ones(size(A,1),1)*(-dir)];
progress=unique(progress,'rows');
while ~isempty(intersect(progress,B,'rows'))
    [a,~,b]=intersect(progress,B,'rows');
    A=[A;a];
    A=unique(A,'rows');
    B(b,:)=[];
    progress=[A;A+ones(size(A,1),1)*dir;...
                A+ones(size(A,1),1)*(-dir)];
    progress=unique(progress,'rows');
end
list=A;
end

m文件3:
double_three.m |(判断是否三三)

function boolean=double_three(map,pos)
boolean=0;
map(pos(1)+10,pos(2)+10)=1;
boolean1=0;boolean2=0;boolean3=0;boolean4=0;
end_point11=get_endpoint([0 1],pos);
end_point12=get_endpoint([0 -1],pos);

end_point21=get_endpoint([1 0],pos);
end_point22=get_endpoint([-1 0],pos);

end_point31=get_endpoint([1 1],pos);
end_point32=get_endpoint([-1 -1],pos);

end_point41=get_endpoint([1 -1],pos);
end_point42=get_endpoint([-1 1],pos);
if get_connection_dir([0 1],pos)==3&&...
   map(end_point11(1)+10,end_point11(2)+10-1)~=1&&...
   map(end_point12(1)+10,end_point12(2)+10+1)~=1&&...
   abs(end_point11(2)-end_point12(2))>=7
    boolean1=1;
end
if get_connection_dir([1 0],pos)==3&&...
   map(end_point21(1)+10-1,end_point21(2)+10)~=1&&...
   map(end_point22(1)+10+1,end_point22(2)+10)~=1&&...
   abs(end_point21(1)-end_point22(1))>=7
    boolean2=1;
end
if get_connection_dir([1 1],pos)==3&&...
   map(end_point31(1)+10-1,end_point31(2)+10-1)~=1&&...
   map(end_point32(1)+10+1,end_point32(2)+10+1)~=1&&...
   abs(end_point31(2)-end_point32(2))>=7
    boolean3=1;
end
if get_connection_dir([1 -1],pos)==3&&...
   map(end_point41(1)+10-1,end_point41(2)+10+1)~=1&&...
   map(end_point42(1)+10+1,end_point42(2)+10-1)~=1&&...
   abs(end_point41(2)-end_point42(2))>=7
    boolean4=1;
end
if boolean1+boolean2+boolean3+boolean4>=2
    boolean=1;
end

    function sums=get_connection_dir(dir,pos)
        sums=0;
        for i=-3:1:3
            if any(abs(pos+dir.*i)>9)
            else
                temp_pos=pos+dir.*i;
                if map(temp_pos(1)+10,temp_pos(2)+10)==1
                    sums=sums+1;
                end
            end
        end
    end

    function endpoint=get_endpoint(dir,pos)
        for i=1:5
            temp_pos=pos+dir.*i;
            if any(abs(pos+dir.*i)>9)
                endpoint=pos+dir.*i;break;
            end
            if map(temp_pos(1)+10,temp_pos(2)+10)==-1
                endpoint=pos+dir.*i;break;
            end
            endpoint=pos+dir.*i;
        end
    end
end

m文件4:
double_four.m |(判断是否四四)

function boolean=double_four(mat,map,pos)
boolean=0;
temp_list_1=get_connection_area2(mat,pos,1);
temp_list_2=get_connection_area2(mat,pos,2);
temp_list_3=get_connection_area2(mat,pos,3);
temp_list_4=get_connection_area2(mat,pos,4);
temp_list_1_endpoint=[temp_list_1;temp_list_1+ones(size(temp_list_1,1),1)*[0 1];...
                                  temp_list_1+ones(size(temp_list_1,1),1)*[0 -1]];
temp_list_2_endpoint=[temp_list_2;temp_list_2+ones(size(temp_list_2,1),1)*[1 0];...
                                  temp_list_2+ones(size(temp_list_2,1),1)*[-1 0]];
temp_list_3_endpoint=[temp_list_3;temp_list_3+ones(size(temp_list_3,1),1)*[1 1];...
                                  temp_list_3+ones(size(temp_list_3,1),1)*[-1 -1]];
temp_list_4_endpoint=[temp_list_4;temp_list_4+ones(size(temp_list_4,1),1)*[1 -1];...
                                  temp_list_4+ones(size(temp_list_4,1),1)*[-1 1]]; 
temp_list_1_endpoint=unique(temp_list_1_endpoint,'rows');  
temp_list_2_endpoint=unique(temp_list_2_endpoint,'rows');
temp_list_3_endpoint=unique(temp_list_3_endpoint,'rows');
temp_list_4_endpoint=unique(temp_list_4_endpoint,'rows');
[~,d1,~]=intersect(temp_list_1_endpoint,temp_list_1,'rows');
[~,d2,~]=intersect(temp_list_2_endpoint,temp_list_2,'rows');
[~,d3,~]=intersect(temp_list_3_endpoint,temp_list_3,'rows');
[~,d4,~]=intersect(temp_list_4_endpoint,temp_list_4,'rows');
temp_list_1_endpoint(d1,:)=[];
temp_list_2_endpoint(d2,:)=[];
temp_list_3_endpoint(d3,:)=[];
temp_list_4_endpoint(d4,:)=[];
temp_list_1_endpoint(abs(temp_list_1_endpoint(:,1))>9,:)=[];
temp_list_1_endpoint(abs(temp_list_1_endpoint(:,2))>9,:)=[];
temp_list_2_endpoint(abs(temp_list_2_endpoint(:,1))>9,:)=[];
temp_list_2_endpoint(abs(temp_list_2_endpoint(:,2))>9,:)=[];
temp_list_3_endpoint(abs(temp_list_3_endpoint(:,1))>9,:)=[];
temp_list_3_endpoint(abs(temp_list_3_endpoint(:,2))>9,:)=[];
temp_list_4_endpoint(abs(temp_list_4_endpoint(:,1))>9,:)=[];
temp_list_4_endpoint(abs(temp_list_4_endpoint(:,2))>9,:)=[];
boolean1=0;boolean2=0;boolean3=0;boolean4=0;

if sum(map(temp_list_1_endpoint(:,1)+10+(temp_list_1_endpoint(:,2)+9).*19)==0)==2&&size(temp_list_1,1)==4
   boolean1=1;
end
if sum(map(temp_list_2_endpoint(:,1)+10+(temp_list_2_endpoint(:,2)+9).*19)==0)==2&&size(temp_list_2,1)==4
   boolean2=1;
end
if sum(map(temp_list_3_endpoint(:,1)+10+(temp_list_3_endpoint(:,2)+9).*19)==0)==2&&size(temp_list_3,1)==4
   boolean3=1;
end
if sum(map(temp_list_4_endpoint(:,1)+10+(temp_list_4_endpoint(:,2)+9).*19)==0)==2&&size(temp_list_4,1)==4
   boolean4=1;
end
if boolean1+boolean2+boolean3+boolean4>=2
    boolean=1;
end
end

m文件5:
long_connect.m |(判断是否长联)

function boolean=long_connect(mat,pos)
    boolean=0;
        if size(get_connection_area2(mat,pos,1),1)>=6||...
           size(get_connection_area2(mat,pos,2),1)>=6||...
           size(get_connection_area2(mat,pos,3),1)>=6||...
           size(get_connection_area2(mat,pos,3),1)>=6
                boolean=1;
        end

end

2.5 围五子棋

简介:
围棋和五子棋的结合,被围住的棋子会改变颜色,连成五子胜利。

游戏支持键盘下棋和鼠标下棋两种下棋方式

键盘下棋:

  1. ↑↓←→键移动棋子
  2. 空格键(space)下棋
  3. Backspace键悔棋
  4. 'r’键重新开始

鼠标下棋:

  1. 左键下棋
  2. 右键悔棋
  3. 左右键同时按下重新开始

函数分为三个m文件

游戏效果:
在这里插入图片描述
完整代码:
m文件1:
wei_fiveinrows.m | (围五子棋程序的主体)

function wei_fiveinrows
%图形界面初始化:
    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
%按键函数初始化设置:
    set(gcf,'KeyPressFcn',@key,'tag','keyset')
    set(gcf,'WindowButtonDownFcn',@buttondown)
%全局变量:
global winner;
global turn;
global checher_board
global black;
global white;
global postion;
global plotblack;
global plotwhite;
global plotpostion;
global bout;
global warehouse;
init()
    function init(~,~)
        %初始化前清除原有图像:
        delete(findobj('tag','piece'));
        delete(findobj('tag','redcross'));
        delete(findobj('type','line'));
        delete(findobj('type','patch'));
        
        %棋盘绘制:
        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')
        
        %棋子棋盘数值初始化:
        winner=0;postion=[0 0];turn=1;
        black=[20,20 0];white=[-20,-20 0];
        black(1,:)=[];white(1,:)=[];
        checher_board=zeros(19,19);
        
        bout=1;
        warehouse{bout,1}=checher_board;
        warehouse{bout,2}=turn;
        warehouse{bout,3}=black;
        warehouse{bout,4}=white;
        
        %绘制函数初始化:
        plotblack=scatter(gca,black(:,1),black(:,2),150,'k','filled','tag','piece');
        plotwhite=scatter(gca,white(:,1),white(:,2),150,'w','filled','tag','piece');
        plotpostion=scatter(gca,postion(1,1),postion(1,2),150,'rx','tag','redcross');
    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 'space',set_piece();
            case 'backspace',undo();
            case 'r',init();
        end
        postion(postion>9)=-9;
        postion(postion<-9)=9;
        redraw()
    end

    function buttondown(~,~)
        xy=get(gca,'CurrentPoint');
        xp=xy(1,2);yp=xy(1,1);
        pos=[yp,xp];
        pos=round(pos);
        if all(abs(pos)<=9)
            postion=round(pos);
            if strcmp(get(gcf,'SelectionType'),'alt'),undo();end
            if strcmp(get(gcf,'SelectionType'),'open'),undo();end
            if strcmp(get(gcf,'SelectionType'),'normal'),set_piece();end
            if strcmp(get(gcf,'SelectionType'),'extend'),init();end
            redraw()
        end
    end

    function set_piece(~,~)
        if checher_board(postion(1)+10,postion(2)+10)==0&&winner==0
            switch turn
                case 1
                    checher_board(postion(1)+10,postion(2)+10)=1;
                    surrounded=weather_surrounded(checher_board,postion+[10 10]);
                    black=[black;[postion,surrounded]];                        
                case 0
                    checher_board(postion(1)+10,postion(2)+10)=-1;
                    surrounded=weather_surrounded(checher_board,postion+[10 10]);
                    white=[white;[postion,surrounded]];        
            end
            black=[black(:,1:2),weather_surrounded(checher_board,black(:,1:2)+[10 10])];
            white=[white(:,1:2),weather_surrounded(checher_board,white(:,1:2)+[10 10])];
            if ~isempty(intersect(postion+[0 1],[black(:,1:2);white(:,1:2)],'rows')),change_color(postion+[0 1]);end
            if ~isempty(intersect(postion+[0 -1],[black(:,1:2);white(:,1:2)],'rows')),change_color(postion+[0 -1]);end
            if ~isempty(intersect(postion+[1 0],[black(:,1:2);white(:,1:2)],'rows')),change_color(postion+[1 0]);end
            if ~isempty(intersect(postion+[-1 0],[black(:,1:2);white(:,1:2)],'rows')),change_color(postion+[-1 0]);end
            turn=mod(turn+1,2);
            bout=bout+1;
            warehouse{bout,1}=checher_board;
            warehouse{bout,2}=turn;
            warehouse{bout,3}=black;
            warehouse{bout,4}=white;
        end     
    end

    function undo(~,~)
        if winner~=0
            winner=0;
            delete(findobj('tag','clues'));
            plotpostion=scatter(gca,postion(1,1),postion(1,2),150,'rx','tag','redcross');
            bout=bout-1;
            warehouse(end,:)=[];
            checher_board=warehouse{bout,1};
            turn=warehouse{bout,2};
            black=warehouse{bout,3};
            white=warehouse{bout,4};
        else
            if bout~=1
            bout=bout-1;
            warehouse(end,:)=[];
            checher_board=warehouse{bout,1};
            turn=warehouse{bout,2};
            black=warehouse{bout,3};
            white=warehouse{bout,4};
            end
        end
    end

    function change_color(pos)
        switch 1
            case ~isempty(intersect(pos,black(:,1:2),'rows'))
                connection_area=get_connection_area(black(:,1:2),pos);
                [~,b,~]=intersect(black(:,1:2),connection_area,'rows');
                if all(black(b,3))
                    checher_board((black(b,1)+10)+((black(b,2)+10)-1).*19)=-1;
                    white=[white;black(b,:)];
                    black(b,:)=[]; 
                    
                end
            case ~isempty(intersect(pos,white(:,1:2),'rows'))
                connection_area=get_connection_area(white(:,1:2),pos);
                [~,w,~]=intersect(white(:,1:2),connection_area,'rows');
                if all(white(w,3))
                    checher_board((white(w,1)+10)+((white(w,2)+10)-1).*19)=1;
                    black=[black;white(w,:)];
                    white(w,:)=[];              
                end
        end
    end

    function redraw(~,~)
        if winner==0
            set(plotblack,'XData',black(:,1),'YData',black(:,2))
            set(plotwhite,'XData',white(:,1),'YData',white(:,2))
            set(plotpostion,'XData',postion(:,1),'YData',postion(:,2))
        judge()
        end
    end

    function judge(~,~)
        temp_mat_1=checher_board+[zeros(19,1),checher_board(:,1:18)]...
                                +[zeros(19,2),checher_board(:,1:17)]...
                                +[checher_board(:,2:end),zeros(19,1)]...
                                +[checher_board(:,3:end),zeros(19,2)];
        temp_mat_2=checher_board+[zeros(1,19);checher_board(1:18,:)]...
                                +[zeros(2,19);checher_board(1:17,:)]...
                                +[checher_board(2:end,:);zeros(1,19)]...
                                +[checher_board(3:end,:);zeros(2,19)];
        temp_mat_3=checher_board+[zeros(1,19);[zeros(18,1),checher_board(1:18,1:18)]]...
                                +[zeros(2,19);[zeros(17,2),checher_board(1:17,1:17)]]...
                                +[[checher_board(2:end,2:end),zeros(18,1)];zeros(1,19)]...
                                +[[checher_board(3:end,3:end),zeros(17,2)];zeros(2,19)];
        temp_mat_4=checher_board+[[zeros(18,1),checher_board(2:end,1:18)];zeros(1,19)]...
                                +[[zeros(17,2),checher_board(3:end,1:17)];zeros(2,19)]...
                                +[zeros(1,19);[checher_board(1:18,2:end),zeros(18,1)]]...
                                +[zeros(2,19);[checher_board(1:17,3:end),zeros(17,2)]];
        switch 1
            case any(any(temp_mat_1==5))||any(any(temp_mat_1==-5)),winner=any(any(temp_mat_1==5))-any(any(temp_mat_1==-5));
                [pos_x,pos_y]=find(temp_mat_1(:,:)==winner*5);endpoint=[pos_x(1),pos_y(1);pos_x(1),pos_y(1)]+[0 2;0 -2];
            case any(any(temp_mat_2==5))||any(any(temp_mat_2==-5)),winner=any(any(temp_mat_2==5))-any(any(temp_mat_2==-5));
                [pos_x,pos_y]=find(temp_mat_2(:,:)==winner*5);endpoint=[pos_x(1),pos_y(1);pos_x(1),pos_y(1)]+[2 0;-2 0];
            case any(any(temp_mat_3==5))||any(any(temp_mat_3==-5)),winner=any(any(temp_mat_3==5))-any(any(temp_mat_3==-5));
                [pos_x,pos_y]=find(temp_mat_3(:,:)==winner*5);endpoint=[pos_x(1),pos_y(1);pos_x(1),pos_y(1)]+[2 2;-2 -2];
            case any(any(temp_mat_4==5))||any(any(temp_mat_4==-5)),winner=any(any(temp_mat_4==5))-any(any(temp_mat_4==-5));
                [pos_x,pos_y]=find(temp_mat_4(:,:)==winner*5);endpoint=[pos_x(1),pos_y(1);pos_x(1),pos_y(1)]+[2 -2;-2 2];
        end
        if winner~=0
            plot(endpoint(:,1)-10,endpoint(:,2)-10,'color',[0.8 0 0],'linewidth',2,'tag','clues')
            delete(findobj('tag','redcross'))
        end
    end
end

m文件2:
weather_surrounded.m | (判断当前位置周围是否有空位)

function boolean=weather_surrounded(mat,pos)
%to detect if the piece is surrounded
%the mat is a matrix composed of 1,0,-1
[m,n]=size(mat);
temp_mat=abs(mat);
new_mat=temp_mat+[ones(m,1),temp_mat(:,1:n-1)]...
                +[temp_mat(:,2:end),ones(m,1)]...
                +[ones(1,n);temp_mat(1:m-1,:)]...
                +[temp_mat(2:end,:);ones(1,n)];
boolean=new_mat(pos(:,1)+(pos(:,2)-1).*m)==5;
end

m文件3:
get_connection_area.m | (获取当前位置联通区域)

function list=get_connection_area(pos_list,pos)
%always add new numbers from partb to parta
A=pos;
B=pos_list;
progress=[A;A+ones(size(A,1),1)*[0 1];...
            A+ones(size(A,1),1)*[0 -1];...
            A+ones(size(A,1),1)*[1 0];...
            A+ones(size(A,1),1)*[-1 0]];
progress=unique(progress,'rows');
while ~isempty(intersect(progress,B,'rows'))
    [a,~,b]=intersect(progress,B,'rows');
    A=[A;a];
    A=unique(A,'rows');
    B(b,:)=[];
    progress=[A;A+ones(size(A,1),1)*[0 1];...
            A+ones(size(A,1),1)*[0 -1];...
            A+ones(size(A,1),1)*[1 0];...
            A+ones(size(A,1),1)*[-1 0]];
    progress=unique(progress,'rows');
end
list=A;
end

2.6 六子棋

简介:
与五子棋不同的是,六子棋黑方先手第一步可下一子,之后双方轮流下棋每次可下两子

完整代码:
six_in_rows.m | (六子棋完整代码)

function six_in_rows
%图形界面初始化:
    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
%按键函数初始化设置:
    set(gcf,'KeyPressFcn',@key,'tag','keyset')
    set(gcf,'WindowButtonDownFcn',@buttondown)
%全局变量:
global winner;
global turn;
global checher_board
global black;
global white;
global postion;
global plotblack;
global plotwhite;
global plotpostion;
global alternate;
init()
    function init(~,~)
        %初始化前清除原有图像:
        delete(findobj('tag','piece'));
        delete(findobj('tag','redcross'));
        delete(findobj('type','line'));
        delete(findobj('type','patch'));
        
        %棋盘绘制:
        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')
        
        %棋子棋盘数值初始化:
        winner=0;postion=[0 0];turn=2;
        black=[20,20];white=[-20,-20];
        black(1,:)=[];white(1,:)=[];
        checher_board=zeros(19,19);
        alternate=[1 1 0 0];
        
        %绘制函数初始化:
        plotblack=scatter(gca,black(:,1),black(:,2),150,'k','filled','tag','piece');
        plotwhite=scatter(gca,white(:,1),white(:,2),150,'w','filled','tag','piece');
        plotpostion=scatter(gca,postion(1,1),postion(1,2),150,'rx','tag','redcross');
    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 'space',set_piece();
            case 'backspace',undo();
            case 'r',init();
        end
        postion(postion>9)=-9;
        postion(postion<-9)=9;
        redraw()
    end

    function buttondown(~,~)
        xy=get(gca,'CurrentPoint');
        xp=xy(1,2);yp=xy(1,1);
        pos=[yp,xp];
        pos=round(pos);
        if all(abs(pos)<=9)
            postion=round(pos);
            if strcmp(get(gcf,'SelectionType'),'alt'),undo();end
            if strcmp(get(gcf,'SelectionType'),'open'),undo();end
            if strcmp(get(gcf,'SelectionType'),'normal'),set_piece();end
            if strcmp(get(gcf,'SelectionType'),'extend'),init();end
            redraw()
        end
    end

    function set_piece(~,~)
        if checher_board(postion(1)+10,postion(2)+10)==0&&winner==0
            switch alternate(turn)
                case 1
                    checher_board(postion(1)+10,postion(2)+10)=1;
                    black=[black;postion];                        
                case 0
                    checher_board(postion(1)+10,postion(2)+10)=-1;
                    white=[white;postion];        
            end
            turn=mod(turn,4)+1;
        end     
    end

    function redraw(~,~)
        if winner==0
            set(plotblack,'XData',black(:,1),'YData',black(:,2))
            set(plotwhite,'XData',white(:,1),'YData',white(:,2))
            set(plotpostion,'XData',postion(:,1),'YData',postion(:,2))
        end
        judge()
    end

    function judge(~,~)
        temp_mat_1=checher_board+[zeros(19,1),checher_board(:,1:18)]...
                                +[zeros(19,2),checher_board(:,1:17)]...
                                +[zeros(19,3),checher_board(:,1:16)]...
                                +[zeros(19,4),checher_board(:,1:15)]...
                                +[zeros(19,5),checher_board(:,1:14)];
        temp_mat_2=checher_board+[zeros(1,19);checher_board(1:18,:)]...
                                +[zeros(2,19);checher_board(1:17,:)]...
                                +[zeros(3,19);checher_board(1:16,:)]...
                                +[zeros(4,19);checher_board(1:15,:)]...
                                +[zeros(5,19);checher_board(1:14,:)];
        temp_mat_3=checher_board+[zeros(1,19);[zeros(18,1),checher_board(1:18,1:18)]]...
                                +[zeros(2,19);[zeros(17,2),checher_board(1:17,1:17)]]...
                                +[zeros(3,19);[zeros(16,3),checher_board(1:16,1:16)]]...
                                +[zeros(4,19);[zeros(15,4),checher_board(1:15,1:15)]]...
                                +[zeros(5,19);[zeros(14,5),checher_board(1:14,1:14)]];
        temp_mat_4=checher_board+[[zeros(18,1),checher_board(2:end,1:18)];zeros(1,19)]...
                                +[[zeros(17,2),checher_board(3:end,1:17)];zeros(2,19)]...
                                +[[zeros(16,3),checher_board(4:end,1:16)];zeros(3,19)]...
                                +[[zeros(15,4),checher_board(5:end,1:15)];zeros(4,19)]...
                                +[[zeros(14,5),checher_board(6:end,1:14)];zeros(5,19)];
        switch 1
            case any(any(temp_mat_1==6))||any(any(temp_mat_1==-6)),winner=any(any(temp_mat_1==6))-any(any(temp_mat_1==-6));
                [pos_x,pos_y]=find(temp_mat_1(:,:)==winner*6);endpoint=[pos_x(1),pos_y(1);pos_x(1),pos_y(1)]+[0 0;0 -5];
            case any(any(temp_mat_2==6))||any(any(temp_mat_2==-6)),winner=any(any(temp_mat_2==6))-any(any(temp_mat_2==-6));
                [pos_x,pos_y]=find(temp_mat_2(:,:)==winner*6);endpoint=[pos_x(1),pos_y(1);pos_x(1),pos_y(1)]+[0 0;-5 0];
            case any(any(temp_mat_3==6))||any(any(temp_mat_3==-6)),winner=any(any(temp_mat_3==6))-any(any(temp_mat_3==-6));
                [pos_x,pos_y]=find(temp_mat_3(:,:)==winner*6);endpoint=[pos_x(1),pos_y(1);pos_x(1),pos_y(1)]+[0 0;-5 -5];
            case any(any(temp_mat_4==6))||any(any(temp_mat_4==-6)),winner=any(any(temp_mat_4==6))-any(any(temp_mat_4==-6));
                [pos_x,pos_y]=find(temp_mat_4(:,:)==winner*6);endpoint=[pos_x(1),pos_y(1);pos_x(1),pos_y(1)]+[0 0;5 -5];
        end
        if winner~=0
            plot(endpoint(:,1)-10,endpoint(:,2)-10,'color',[0.8 0 0],'linewidth',2,'tag','clues')
            delete(findobj('tag','redcross'))
        end
    end

    function undo(~,~)
        if winner~=0
            winner=0;
            delete(findobj('tag','clues'));
            plotpostion=scatter(gca,postion(1,1),postion(1,2),150,'rx','tag','redcross');
        end
        if any(any(checher_board~=0))
            turn=mod(turn+2,4)+1;
            switch 1
                case turn==1||turn==2,checher_board(black(end,1)+10,black(end,2)+10)=0;black(end,:)=[];
                case turn==3||turn==4,checher_board(white(end,1)+10,white(end,2)+10)=0;white(end,:)=[];
            end
        end
    end
        


end

2.7 九子棋

简介:
对弈双方各有九个棋子,轮流下到特殊棋盘的空位上。

当有己方三子连成一线时,可吃掉对方未连成一线的棋子。

当所有棋子被摆放到棋盘上时,双方轮流移动棋子(向棋子相邻方向),并通过移动棋子将三子连成一线来吃对方棋子。

当一方只剩三颗棋子时,移动方向可以是棋盘上的任意空位。

当将对手的棋子吃到只剩两颗即为获胜。

目前只支持鼠标移动

游戏效果:
落子阶段:
在这里插入图片描述
移子阶段:
在这里插入图片描述
只剩三子:
在这里插入图片描述

完整代码:

function mill
%图形界面初始化:
    axis equal
    axis([-3.5,3.5,-3.5,3.5])
    set(gca,'xtick',[],'ytick',[],'xcolor','w','ycolor','w')
    set(gca,'color',[0.9333 0.8275 0.6118])
    hold on
%按键函数初始化设置:
    set(gcf,'WindowButtonDownFcn',@buttondown)
global winner;
global turn;
global red;
global blue;
global red_store;
global blue_store;
global all_piece;
global checher_board
global postion;
global plotred;
global plotblue;
global plotallpiece1;
global plotallpiece2;
global plotpostion1;
global plotpostion2;
global pos_avilable;
global pos_arrivable;
global plotarrivable;
global pos_selected;
global pos_appropriated;
global nowaplace;

init()
    function init(~,~)
        %初始化前清除原有图像:
        delete(findobj('tag','piece'));
        delete(findobj('tag','select'));
        delete(findobj('type','line'));
        delete(findobj('type','patch'));
        
        l1=[1 1;1 -1;-1 -1;-1 1;1 1];
        plot(l1(:,1).*1.02,l1(:,2).*1.02,'color',[0 0 0],'linewidth',4);
        plot(l1(:,1).*2.02,l1(:,2).*2.02,'color',[0 0 0],'linewidth',4);
        plot(l1(:,1).*3.02,l1(:,2).*3.02,'color',[0 0 0],'linewidth',4);
        
        plot(l1(:,1).*1.07,l1(:,2).*1.07,'color',[0.5255 0.2745 0.2353],'linewidth',4);
        plot(l1(:,1).*2.07,l1(:,2).*2.07,'color',[0.5255 0.2745 0.2353],'linewidth',4);
        plot(l1(:,1).*3.07,l1(:,2).*3.07,'color',[0.5255 0.2745 0.2353],'linewidth',4);
        
        plot([0 0],[1 3],'color',[0.5255 0.2745 0.2353],'linewidth',4);
        plot([0 0],[-1 -3],'color',[0.5255 0.2745 0.2353],'linewidth',4);
        plot([1 3],[0 0],'color',[0.5255 0.2745 0.2353],'linewidth',4);
        plot([-1 -3],[0 0],'color',[0.5255 0.2745 0.2353],'linewidth',4);
        
        red=[0 0];red(1,:)=[];
        blue=[0 0];blue(1,:)=[];
        turn=[1 0];
        
        winner=0;
        
        postion=[0 0];
        red_store=9;
        blue_store=9;
        all_piece=[red;blue];
        checher_board=zeros(7,7);
        
        pos_avilable=[1 0;2 0;3 0;-1 0;-2 0;-3 0;...
                      0 1;0 2;0 3;0 -1;0 -2;0 -3;...
                      1 1;2 2;3 3;-1 -1;-2 -2;-3 -3;...
                      1 -1;2 -2;3 -3;-1 1;-2 2;-3 3];
        pos_appropriated=pos_avilable;
        pos_arrivable=[1 1];
        pos_arrivable(1,:)=[];
        pos_selected=[];
        nowaplace=[];

        %绘制函数初始化:
        plotred=scatter(gca,red(:,1),red(:,2),800,'k','filled','CData',[0.8157 0.4275 0.0588],'tag','piece');
        plotblue=scatter(gca,blue(:,1),blue(:,2),800,'w','filled','CData',[0 0.5255 0.9255],'tag','piece');
        plotallpiece1=scatter(gca,all_piece(:,1),all_piece(:,2),450,'CData',[0.75 0.75 0.75],'linewidth',1,'tag','piece');
        plotallpiece2=scatter(gca,all_piece(:,1),all_piece(:,2),810,'CData',[0 0 0],'linewidth',1,'tag','piece');
        plotpostion1=scatter(gca,postion(1,1),postion(1,2),60,'s','filled','CData',[1.0000 1.0000 0.9843],'tag','select');
        plotpostion2=scatter(gca,postion(1,1),postion(1,2),60,'s','CData',[0.6627 0.8706 1.0000],'linewidth',2,'tag','select');
        plotarrivable=scatter(gca,pos_arrivable(:,1),pos_arrivable(:,2),100,'c','CData',[0.5373 0.9059 0.3255],'linewidth',4,'tag','gc');
    end

    function buttondown(~,~)
        xy=get(gca,'CurrentPoint');
        xp=xy(1,2);yp=xy(1,1);
        pos=[yp,xp];
        pos=round(pos);
        if all(abs(pos)<=3)&&~isempty(intersect(pos,pos_avilable,'rows'))
            postion=pos;
            switch 1
                case turn(1)==1&&turn(2)==0
                    if red_store>0&&checher_board(postion(1)+4,postion(2)+4)==0
                        red_store=red_store-1;
                        [~,r,~]=intersect(pos_appropriated,postion,'rows');
                        pos_appropriated(r,:)=[];
                        red=[red;postion];
                        checher_board(postion(1)+4,postion(2)+4)=1;
                        all_piece=[red;blue];
                        if  (sum(checher_board(postion(1)+4,:))*(postion(1)~=0)...
                                +sum(checher_board(postion(1)+4,(postion(1)~=0)*[1 1 1]+(postion(1)==0)*((postion(2)>0)*(5:7)+(postion(2)<0)*(1:3))))*(postion(1)==0))==3||...
                            (sum(checher_board(:,postion(2)+4))*(postion(2)~=0)...
                                +sum(checher_board((postion(2)~=0)*[1 1 1]+(postion(2)==0)*((postion(1)>0)*(5:7)+(postion(1)<0)*(1:3)),postion(2)+4))*(postion(2)==0))==3
                            turn=[0 -1];
                            for i=1:size(blue,1)
                                if (sum(checher_board(blue(i,1)+4,:))*(blue(i,1)~=0)...
                                        +sum(checher_board(blue(i,1)+4,(blue(i,1)~=0)*[1 1 1]+(blue(i,1)==0)*((blue(i,2)>0)*(5:7)+(blue(i,2)<0)*(1:3))))*(blue(i,1)==0))==-3||...
                                    (sum(checher_board(:,blue(i,2)+4))*(blue(i,2)~=0)...
                                        +sum(checher_board((blue(i,2)~=0)*[1 1 1]+(blue(i,2)==0)*((blue(i,1)>0)*(5:7)+(blue(i,1)<0)*(1:3)),blue(i,2)+4))*(blue(i,2)==0))==-3
                                else
                                    pos_arrivable=[pos_arrivable;blue(i,:)];
                                end 
                            end
                            if isempty(pos_arrivable)
                                turn=[0 0];
                            end
                        else
                            turn=[mod(turn(1)+1,2),0];
                        end
                    else
                        if red_store==0
                            switch 1
                                case checher_board(postion(1)+4,postion(2)+4)==1
                                    if size(red,1)>3
                                        rows_search1=pos_appropriated(pos_appropriated(:,2)==postion(2),1);
                                        rows_search1=rows_search1(abs(rows_search1-postion(1))==min(abs(rows_search1-postion(1))));
                                        cols_search1=pos_appropriated(pos_appropriated(:,1)==postion(1),2);
                                        cols_search1=cols_search1(abs(cols_search1-postion(2))==min(abs(cols_search1-postion(2))));                               
                                        rows_search2=pos_avilable(pos_avilable(:,2)==postion(2),1);
                                        rows_search2(rows_search2==postion(1))=[];
                                        rows_search2=rows_search2(abs(rows_search2-postion(1))==min(abs(rows_search2-postion(1))));
                                        cols_search2=pos_avilable(pos_avilable(:,1)==postion(1),2);
                                        cols_search2(cols_search2==postion(2))=[];
                                        cols_search2=cols_search2(abs(cols_search2-postion(2))==min(abs(cols_search2-postion(2))));
                                        pos_arrivable1=[[rows_search1,postion(2).*ones(length(rows_search1),1)];...
                                            [postion(1).*ones(length(cols_search1),1),cols_search1]];
                                        pos_arrivable2=[[rows_search2,postion(2).*ones(length(rows_search2),1)];...
                                            [postion(1).*ones(length(cols_search2),1),cols_search2]];
                                        pos_arrivable=intersect(pos_arrivable1,pos_arrivable2,'rows');
                                    elseif size(red,1)==3
                                        pos_arrivable=pos_appropriated;                                        
                                    end
                                    nowaplace=postion;
                                case checher_board(postion(1)+4,postion(2)+4)==-1
                                    pos_arrivable(:,:)=[];
                                    nowaplace(:,:)=[];
                                case ~isempty(intersect(postion,pos_arrivable,'rows'))
                                    checher_board(nowaplace(1)+4,nowaplace(2)+4)=0;
                                    red(sum(abs(red-nowaplace),2)==0,:)=[];
                                    red=[red;postion];
                                    checher_board(postion(1)+4,postion(2)+4)=1;
                                    all_piece=[red;blue];    
                                    pos_appropriated(sum(abs(pos_appropriated-postion),2)==0,:)=[];
                                    pos_appropriated=[pos_appropriated;nowaplace];
                                    pos_arrivable(:,:)=[];                            
                                    if (sum(checher_board(postion(1)+4,:))*(postion(1)~=0)...
                                            +sum(checher_board(postion(1)+4,(postion(1)~=0)*[1 1 1]+(postion(1)==0)*((postion(2)>0)*(5:7)+(postion(2)<0)*(1:3))))*(postion(1)==0))==3||...
                                        (sum(checher_board(:,postion(2)+4))*(postion(2)~=0)...
                                            +sum(checher_board((postion(2)~=0)*[1 1 1]+(postion(2)==0)*((postion(1)>0)*(5:7)+(postion(1)<0)*(1:3)),postion(2)+4))*(postion(2)==0))==3
                                        turn=[0 -1];
                                        for i=1:size(blue,1)
                                            if (sum(checher_board(blue(i,1)+4,:))*(blue(i,1)~=0)...
                                                    +sum(checher_board(blue(i,1)+4,(blue(i,1)~=0)*[1 1 1]+(blue(i,1)==0)*((blue(i,2)>0)*(5:7)+(blue(i,2)<0)*(1:3))))*(blue(i,1)==0))==-3||...
                                                (sum(checher_board(:,blue(i,2)+4))*(blue(i,2)~=0)...
                                                    +sum(checher_board((blue(i,2)~=0)*[1 1 1]+(blue(i,2)==0)*((blue(i,1)>0)*(5:7)+(blue(i,1)<0)*(1:3)),blue(i,2)+4))*(blue(i,2)==0))==-3
                                            else
                                                pos_arrivable=[pos_arrivable;blue(i,:)];
                                            end
                                        end
                                        if isempty(pos_arrivable)
                                            turn=[0 0];
                                        end
                                    
                                    else
                                        turn=[mod(turn(1)+1,2),0];
                                    end
                            end
                        end
                    end
                                     
                case turn(1)==0&&turn(2)==0
                    if blue_store>0&&checher_board(postion(1)+4,postion(2)+4)==0
                        blue_store=blue_store-1;
                        [~,b,~]=intersect(pos_appropriated,postion,'rows');
                        pos_appropriated(b,:)=[];
                        blue=[blue;postion];
                        checher_board(postion(1)+4,postion(2)+4)=-1;
                        all_piece=[red;blue];
                        if (sum(checher_board(postion(1)+4,:))*(postion(1)~=0)...
                                +sum(checher_board(postion(1)+4,(postion(1)~=0)*[1 1 1]+(postion(1)==0)*((postion(2)>0)*(5:7)+(postion(2)<0)*(1:3))))*(postion(1)==0))==-3||...
                            (sum(checher_board(:,postion(2)+4))*(postion(2)~=0)...
                                +sum(checher_board((postion(2)~=0)*[1 1 1]+(postion(2)==0)*((postion(1)>0)*(5:7)+(postion(1)<0)*(1:3)),postion(2)+4))*(postion(2)==0))==-3
                            turn=[1 1];
                            for i=1:size(red,1)
                                if (sum(checher_board(red(i,1)+4,:))*(red(i,1)~=0)...
                                        +sum(checher_board(red(i,1)+4,(red(i,1)~=0)*[1 1 1]+(red(i,1)==0)*((red(i,2)>0)*(5:7)+(red(i,2)<0)*(1:3))))*(red(i,1)==0))==3||...
                                    (sum(checher_board(:,red(i,2)+4))*(red(i,2)~=0)...
                                        +sum(checher_board((red(i,2)~=0)*[1 1 1]+(red(i,2)==0)*((red(i,1)>0)*(5:7)+(red(i,1)<0)*(1:3)),red(i,2)+4))*(red(i,2)==0))==3
                                else
                                    pos_arrivable=[pos_arrivable;red(i,:)];
                                end
                            end
                            if isempty(pos_arrivable)
                                turn=[1 0];
                            end
                        else
                            turn=[mod(turn(1)+1,2),0];
                        end
                    else
                        if blue_store==0
                            switch 1
                                case checher_board(postion(1)+4,postion(2)+4)==-1
                                    if size(blue,1)>3
                                        rows_search1=pos_appropriated(pos_appropriated(:,2)==postion(2),1);
                                        rows_search1=rows_search1(abs(rows_search1-postion(1))==min(abs(rows_search1-postion(1))));
                                        cols_search1=pos_appropriated(pos_appropriated(:,1)==postion(1),2);
                                        cols_search1=cols_search1(abs(cols_search1-postion(2))==min(abs(cols_search1-postion(2))));
                                        rows_search2=pos_avilable(pos_avilable(:,2)==postion(2),1);
                                        rows_search2(rows_search2==postion(1))=[];
                                        rows_search2=rows_search2(abs(rows_search2-postion(1))==min(abs(rows_search2-postion(1))));
                                        cols_search2=pos_avilable(pos_avilable(:,1)==postion(1),2);
                                        cols_search2(cols_search2==postion(2))=[];
                                        cols_search2=cols_search2(abs(cols_search2-postion(2))==min(abs(cols_search2-postion(2))));                    
                                        pos_arrivable1=[[rows_search1,postion(2).*ones(length(rows_search1),1)];...
                                            [postion(1).*ones(length(cols_search1),1),cols_search1]];
                                        pos_arrivable2=[[rows_search2,postion(2).*ones(length(rows_search2),1)];...
                                            [postion(1).*ones(length(cols_search2),1),cols_search2]];
                                        pos_arrivable=intersect(pos_arrivable1,pos_arrivable2,'rows');
                                    elseif size(blue,1)==3
                                        pos_arrivable=pos_appropriated;
                                    end                               
                                        nowaplace=postion;
                                case checher_board(postion(1)+4,postion(2)+4)==1
                                    pos_arrivable(:,:)=[];
                                    nowaplace(:,:)=[];
                                case ~isempty(intersect(postion,pos_arrivable,'rows'))
                                    checher_board(nowaplace(1)+4,nowaplace(2)+4)=0;
                                    blue(sum(abs(blue-nowaplace),2)==0,:)=[];
                                    blue=[blue;postion];
                                    checher_board(postion(1)+4,postion(2)+4)=-1;
                                    all_piece=[red;blue];   
                                    pos_appropriated(sum(abs(pos_appropriated-postion),2)==0,:)=[];
                                    pos_appropriated=[pos_appropriated;nowaplace];
                                    pos_arrivable(:,:)=[];                
                                    if (sum(checher_board(postion(1)+4,:))*(postion(1)~=0)...
                                            +sum(checher_board(postion(1)+4,(postion(1)~=0)*[1 1 1]+(postion(1)==0)*((postion(2)>0)*(5:7)+(postion(2)<0)*(1:3))))*(postion(1)==0))==-3||...
                                       (sum(checher_board(:,postion(2)+4))*(postion(2)~=0)...
                                            +sum(checher_board((postion(2)~=0)*[1 1 1]+(postion(2)==0)*((postion(1)>0)*(5:7)+(postion(1)<0)*(1:3)),postion(2)+4))*(postion(2)==0))==-3
                                        turn=[1 1];
                                        for i=1:size(red,1)
                                            if (sum(checher_board(red(i,1)+4,:))*(red(i,1)~=0)...
                                                    +sum(checher_board(red(i,1)+4,(red(i,1)~=0)*[1 1 1]+(red(i,1)==0)*((red(i,2)>0)*(5:7)+(red(i,2)<0)*(1:3))))*(red(i,1)==0))==3||...
                                                (sum(checher_board(:,red(i,2)+4))*(red(i,2)~=0)...
                                                    +sum(checher_board((red(i,2)~=0)*[1 1 1]+(red(i,2)==0)*((red(i,1)>0)*(5:7)+(red(i,1)<0)*(1:3)),red(i,2)+4))*(red(i,2)==0))==3
                                            else
                                                pos_arrivable=[pos_arrivable;red(i,:)];
                                            end
                                        end
                                        if isempty(pos_arrivable)
                                            turn=[1 0];
                                        end
                                    else
                                        turn=[mod(turn(1)+1,2),0];
                                    end
                            end
                        end
                    end
                    
                    
                case turn(1)==1&&turn(2)==1
                    if ~isempty(intersect(postion,pos_arrivable,'rows'))
                        red(sum(abs(red-postion),2)==0,:)=[];
                        all_piece=[red;blue];
                        checher_board(postion(1)+4,postion(2)+4)=0;
                        pos_appropriated=[pos_appropriated;postion];
                        pos_arrivable(:,:)=[];
                        turn=[1 0];
                    end
                case turn(1)==0&&turn(2)==-1
                    if ~isempty(intersect(postion,pos_arrivable,'rows'))
                        blue(sum(abs(blue-postion),2)==0,:)=[];
                        all_piece=[red;blue];
                        checher_board(postion(1)+4,postion(2)+4)=0;
                        pos_appropriated=[pos_appropriated;postion];
                        pos_arrivable(:,:)=[];
                        turn=[0 0];
                    end
            end
        end
        redraw()
    end

    function redraw(~,~)
        set(plotred,'XData',red(:,1),'YData',red(:,2));
        set(plotblue,'XData',blue(:,1),'YData',blue(:,2));
        set(plotallpiece1,'XData',all_piece(:,1),'YData',all_piece(:,2));
        set(plotallpiece2,'XData',all_piece(:,1),'YData',all_piece(:,2));
        set(plotpostion1,'XData',postion(1,1),'YData',postion(1,2));
        set(plotpostion2,'XData',postion(1,1),'YData',postion(1,2));
        set(plotarrivable,'XData',pos_arrivable(:,1),'YData',pos_arrivable(:,2));
        judge()     
    end
    function judge(~,~)
        switch 1
            case red_store==0&&(size(red,1)==2||(cantmove(red)&&turn(1)==1&&turn(2)==0&&size(red,1)~=3)),winner=-1;
            case blue_store==0&&(size(blue,1)==2||(cantmove(blue)&&turn(1)==0&&turn(2)==0&&size(blue,1)~=3)),winner=1;
        end
        switch winner
            case 1
                buttonName1=questdlg('红方胜利','red win','关闭','重新开始','关闭');
                if isempty(buttonName1),buttonName1='end';end
                if strcmp(buttonName1,'重新开始'),init();
                elseif strcmp(buttonName1,'关闭'),close;
                end
            case -1
                buttonName1=questdlg('蓝方胜利','blue win','关闭','重新开始','关闭');
                if isempty(buttonName1),buttonName1='end';end
                if strcmp(buttonName1,'重新开始'),init();
                elseif strcmp(buttonName1,'关闭'),close;
                end
        end
    end
    function boolean=cantmove(mat)
        pa=[0 0];
        pa(1,:)=[];
        for i=1:size(mat,1)
            rows_search1=pos_appropriated(pos_appropriated(:,2)==mat(i,2),1);
            rows_search1=rows_search1(abs(rows_search1-mat(i,1))==min(abs(rows_search1-mat(i,1))));
            cols_search1=pos_appropriated(pos_appropriated(:,1)==mat(i,1),2);
            cols_search1=cols_search1(abs(cols_search1-mat(i,2))==min(abs(cols_search1-mat(i,2))));
            rows_search2=pos_avilable(pos_avilable(:,2)==mat(i,2),1);
            rows_search2(rows_search2==mat(i,1))=[];
            rows_search2=rows_search2(abs(rows_search2-mat(i,1))==min(abs(rows_search2-mat(i,1))));
            cols_search2=pos_avilable(pos_avilable(:,1)==mat(i,1),2);
            cols_search2(cols_search2==mat(i,2))=[];
            cols_search2=cols_search2(abs(cols_search2-mat(i,2))==min(abs(cols_search2-mat(i,2))));                    
            pos_arrivable1=[[rows_search1,mat(i,2).*ones(length(rows_search1),1)];...
                [mat(i,1).*ones(length(cols_search1),1),cols_search1]];
            pos_arrivable2=[[rows_search2,mat(i,2).*ones(length(rows_search2),1)];...
                [mat(i,1).*ones(length(cols_search2),1),cols_search2]];
            pa=[pa;intersect(pos_arrivable1,pos_arrivable2,'rows')];            
        end
        boolean=isempty(pa);
    end


    

end

2.8黑白棋

游戏效果:
在这里插入图片描述
在这里插入图片描述
完整代码
m文件1:
get_arrivable.m | (可达点 )

function outcome=get_arrivable(board,t)
% 找到找到黑子或者白子可以下棋的位置并输出为outcome
% board :棋盘数组,没有棋子处为0,黑棋为1,白棋为-1
% ===============================================================
% 例:
% 我们若是下一步要下黑棋,就要先找到所有黑棋位置
% 再找到每一个黑棋旁边紧挨着白棋,再顺着该方向[黑棋->白棋]一直找,
% 直到找到紧挨着白棋的空白,该空白是一个黑棋可下子处,所有可下子处的集合
% 就是我们要找的outcome
% ---------------------------------------------------------------
% 但是为了方便代码编写,我们对流程稍加改进(以黑子为例):
% [1] 找到每一个黑子的位置
% [2] j=1:8分八个方向找到该棋子该方向上所有位置的情况
%     例如某黑色棋子(星号)左右情况为:○*○○囗●○○
%     则其右侧方向棋子情况为:○○囗●○○
% [3] 判断某方向棋子第一个是白子,上面例子第一个就是白子
% [4] 如果某防线棋子第一个是白子,删除该方向所有白子
%     上面的例子删除后长这样:囗●
% [5] 如果删除后,第一个位置为空,则该位置为可行位置,上例第一个就是囗,
%     所以是可行位置
% [6] 找到所有可行位置,并删除重复项

% 输出集合初始化
outcome=[0 0];
outcome(1,:)=[];

switch t
    case 1,t=1;
    case 0,t=-1;  
end

% 首先找到棋盘中(黑/白)子位置
[x,y]=find(board==t);
collection=[x,y];

% 上下左右八个方向
dir=[1 0;-1 0;0 1;0 -1;1 1;-1 -1;1 -1;-1 1];


if ~isempty(collection) % 如果棋盘上有棋子(这句话其实有没有都一样)
for i=1:size(collection,1)% 遍历某颜色全部棋子
    for j=1:8% 分别搜索八个方向
        
        % 找到某方向全部棋子,由于棋盘每个方向都最多有八个棋子,所以,以
        % 要检测棋子为中心,向某方向取七个位置就能取到全部位置,超出棋盘
        % 的删掉即可
        temp_set=collection(i,:)+((1:7)')*dir(j,:);
        temp_set(temp_set(:,1)>8|temp_set(:,1)<1,:)=[];
        temp_set(temp_set(:,2)>8|temp_set(:,2)<1,:)=[];
        
        if ~isempty(temp_set)% 如果该棋子某方向还有位置(棋子由可能贴着边,那么那个方向就没有检测的必要)
            % 获取棋子某方向所有位置情况(黑/白/空)
            temp_value=board(temp_set(:,1)+(temp_set(:,2)-1).*8);
            
            % 如果紧挨着的是棋子且为相反颜色
            if temp_value(1)==-t
                
                % 删除该方向全部相反颜色的棋子
                temp_set(temp_value==-t,:)=[];
                temp_value(temp_value==-t)=[];
                
                if ~isempty(temp_set)
                    if temp_value(1)==0% 在紧挨为反色的前提下如果第一个不是反色的是空位置
                        % 将该位置并入结果集合
                        outcome=[outcome;temp_set(1,:)];
                    end  
                end
            end  
        end
    end
end
end

m文件2:
reversi.m | (主函数)

function reversi
%图形界面初始化:
    axis equal
    axis([-0.2 9.2,-0.2 9.2])
    set(gca,'xtick',[],'ytick',[],'xcolor','w','ycolor','w')
    set(gca,'color',[0.6353 0.5451 0.3333])
    hold on
    
    % 下面这个矩阵用来放配色的,并没啥实际用途
    %    [0.2235    0.4902    0.2667
    %     0.3843    0.1569    0.0078
    %     0.7882    0.7647    0.4196
    %     0.6353    0.5451    0.3333
    %     0.1373    0.2902    0.1686];

%按键函数初始化设置:
    set(gcf,'KeyPressFcn',@key,'tag','keyset')
    set(gcf,'WindowButtonDownFcn',@buttondown)
    
%全局变量:
global winner;       %胜者
global turn;         %该哪方下棋
global checher_board %棋盘
global black;        %黑子位置集合
global white;        %白子位置集合

global plotblack;    %用于绘制黑子的函数(图像句柄)
global plotwhite;    %用于绘制白子的函数(图像句柄)

global postion;      %选择的位置(选择位置为可达位置才能落子)
global arrivable;    %可达位置
global plotpostion;  %绘制选择位置的函数(图像句柄)
global plotarrivable;%绘制可达位置的函数(图像句柄)
init()
    function init()
        %初始化前清除原有图像:
        delete(findobj('tag','piece'));
        delete(findobj('tag','gc'));
        delete(findobj('tag','rx'));
        delete(findobj('type','line'));
        delete(findobj('type','patch'));
        
        %棋盘绘制:
        fill([-0.1;9.1;9.1;-0.1;-0.1],[-0.1;-0.1;9.1;9.1;-0.1],[0.3843 0.1569 0.0078])
        fill([0.5;8.5;8.5;0.5;0.5],[0.5;0.5;8.5;8.5;0.5],[0.2235 0.4902 0.2667])
        plot([1.5:1:7.5;1.5:1:7.5],[ones(1,7).*0.5;ones(1,7).*8.5],'color',[0.1373 0.2902 0.1686],'linewidth',0.75)
        plot([ones(1,7).*0.5;ones(1,7).*8.5],[1.5:1:7.5;1.5:1:7.5],'color',[0.1373 0.2902 0.1686],'linewidth',0.75)
        scatter([2.5,6.5,2.5,6.5],[2.5,2.5,6.5,6.5],30,'filled','CData',[0.1373 0.2902 0.1686]);
        numberset={'A','B','C','D','E','F','G','H'};
        for i=1:8
            text(0.2,9-i,num2str(i),...
                'HorizontalAlignment','center',...
                'color',[0.6353 0.5451 0.3333],...
                'FontWeight','bold',...
                'FontSize',12)
            text(i,8.83,numberset{i},...
                'HorizontalAlignment','center',...
                'color',[0.6353 0.5451 0.3333],...
                'FontWeight','bold',...
                'FontSize',12)
        end
        
        %棋子棋盘数值初始化:
        winner=0;turn=1; %无人获胜,黑子先下
        black=[4 4;5 5];white=[4 5;5 4];%初始黑白子位置
        %初始化棋盘
        checher_board=zeros(8,8);
        checher_board(black(:,1)+(black(:,2)-1).*8)=1;
        checher_board(white(:,1)+(white(:,2)-1).*8)=-1;
        postion=[0 0];
        postion(1,:)=[];
        %初始化可达点列表
        arrivable=[5 3;6 4;3 5;4 6];
        
        %绘制函数初始化:
        plotblack=scatter(gca,black(:,1),black(:,2),450,'o','filled','CData',[0.1 0.1 0.1],'tag','piece');
        plotwhite=scatter(gca,white(:,1),white(:,2),450,'o','filled','CData',[0.9 0.9 0.9],'tag','piece');
        plotpostion=scatter(gca,postion(:,1),postion(:,2),50,'o','CData',[0.5059 0.6078 0.3529],'LineWidth',1.5,'tag','gc'); 
        plotarrivable=scatter(gca,arrivable(:,1),arrivable(:,2),150,'x',...
            'CData',[0.7843 0.3412 0.3098].*0.9,'LineWidth',1.5,'tag','rx'); 
        
    end

    %鼠标点击函数
    function buttondown(~,~)
        xy=get(gca,'CurrentPoint');%获取鼠标点击位置
        xp=xy(1,2);yp=xy(1,1);
        pos=[yp,xp];
        pos=round(pos);%取整点,确定点击位置应在棋盘第几行第几列
        if all(abs(pos)<=9)
            postion=pos;
            if strcmp(get(gcf,'SelectionType'),'normal'),set_piece();end%鼠标左键落子
            if strcmp(get(gcf,'SelectionType'),'extend'),init();end%shift+左键重新开始,不太好用建议不用
            redraw()%落完子(为各个数组添加或改变元素后)重新绘制期盼
        end
    end

    % 落子函数
    function set_piece(~,~)
        if ~isempty(intersect(postion,arrivable,'rows'))% 如果选择位置是可达位置
            
            %为黑子或白子集合添加元素
            switch turn
                case 1,black=[black;postion];checher_board(postion(1),postion(2))=1;
                case 0,white=[white;postion];checher_board(postion(1),postion(2))=-1;
            end
            
            %检测被“同化”的棋子并转变颜色
            change_color()
            
            %轮到另一种颜色落子
            turn=mod(turn+1,2); 
            
            %刷新可达集合
            refresh_arrivable()
        end
    end

    function change_color(~,~)
        %从下子位置检测八个方向,更换所有该更换颜色的棋子
        switch turn
            case 1,t=1;
            case 0,t=-1;
        end
        dir=[1 0;-1 0;0 1;0 -1;1 1;-1 -1;1 -1;-1 1];
        
        %集合初始化
        exchange_set=[0 0];
        exchange_set(1,:)=[];
        
        for j=1:8%检测八个方向
            %与检测可达集合类似操作:
            temp_set=postion+((1:7)')*dir(j,:);
            temp_set(temp_set(:,1)>8|temp_set(:,1)<1,:)=[];
            temp_set(temp_set(:,2)>8|temp_set(:,2)<1,:)=[];
            if ~isempty(temp_set)
                
                temp_value=checher_board(temp_set(:,1)+(temp_set(:,2)-1).*8);
                
                %如果离位置最近为反色棋子,找到该集合第一个不是反色棋子的位置
                %如果该位置为同色,便将两同色棋子之间的反色棋子全部替换
                if temp_value(1)==-t
                    cumpoint=find(temp_value~=-t,1);%找到第一个不是反色棋子的位置
                    if ~isempty(cumpoint)
                        if temp_value(cumpoint)==t%如果是同色 
                            exchange_set=[exchange_set;temp_set(1:cumpoint-1,:)];%加入同化集合
                        end
                    end
                end  
            end
        end
        exchange_set=unique(exchange_set,'rows');%删除重复项
        
        %改变棋子集合
        switch turn
            case 1
                black=[black;exchange_set];
                checher_board(exchange_set(:,1)+(exchange_set(:,2)-1).*8)=1;
                [~,w,~]=intersect(white,exchange_set,'rows');
                white(w,:)=[];
            case 0
                white=[white;exchange_set];
                checher_board(exchange_set(:,1)+(exchange_set(:,2)-1).*8)=-1;
                [~,b,~]=intersect(black,exchange_set,'rows');
                black(b,:)=[]; 
        end
    end

    % 刷新可达点集合(调用get_arrivable函数)
    function refresh_arrivable(~,~)
        arrivable=get_arrivable(checher_board,turn);
        % 如果无可落子点,直接转到对手回合并重新检测可达点
        if isempty(arrivable)
            judge()%检测是否有获胜方
            turn=mod(turn+1,2);
            arrivable=get_arrivable(checher_board,turn);
        end
    end

    % 重新绘制和黑子,白子,可达点,当前选择位置
    function redraw(~,~)
        set(plotblack,'XData',black(:,1),'YData',black(:,2))
        set(plotwhite,'XData',white(:,1),'YData',white(:,2))
        set(plotpostion,'XData',postion(:,1),'YData',postion(:,2))
        set(plotarrivable,'XData',arrivable(:,1),'YData',arrivable(:,2))
        if all(all(abs(checher_board)))&&winner==0
            judge()%检测是否有获胜方
        end
    end

    % 判断输赢函数
    function judge()
        % 如果棋盘下满,结束游戏,棋子数量较多的为胜者
        switch 1
            case (all(all(abs(checher_board)))&&size(black,1)>size(white,2))||isempty(white)
                winner=1;
            case (all(all(abs(checher_board)))&&size(white,1)>size(black,2))||isempty(black)
                winner=-1;
            case (all(all(abs(checher_board)))&&size(white,1)==size(black,2))
                winner=3;
        end
        
        %弹出窗口
        if winner~=0
            redraw()
            switch winner
            case 1
                buttonName1=questdlg('黑棋胜利','black win','关闭','重新开始','关闭');
                if isempty(buttonName1),buttonName1='end';end
                if strcmp(buttonName1,'重新开始'),init();
                elseif strcmp(buttonName1,'关闭'),close;
                end
            case -1
                buttonName1=questdlg('白棋胜利','white win','关闭','重新开始','关闭');
                if isempty(buttonName1),buttonName1='end';end
                if strcmp(buttonName1,'重新开始'),init();
                elseif strcmp(buttonName1,'关闭'),close;
                end
            case 3
                buttonName1=questdlg('平局','tie','关闭','重新开始','关闭');
                if isempty(buttonName1),buttonName1='end';end
                if strcmp(buttonName1,'重新开始'),init();
                elseif strcmp(buttonName1,'关闭'),close;
                end
            end
        end
    end

end

3 后记

能看到这里也是辛苦了,毕竟这么长一个文章,大家可以将文中的代码复制下来运行一下,看看其中相似的结构部分,和为了迎合不同功能做出的改变。

欢迎大家指出程序中的问题,之后可能会尝试写一些国际象棋,跳棋之类的棋类游戏,敬请期待。