MATLAB | 如何使用MATLAB制作猫猫围棋小游戏

在刷手机的时候刷到了猫猫围棋小游戏https://puyogo.app/,能够非常直观的教大家围棋的基础规则,甚至网友在学会规则后,柯洁需要经过六个小时深思熟虑才敢应战:

于是我复刻了一个MATLAB版本,运行效果如下:

完整代码

matlab 复制代码
function catgo

% 坐标区域创建
fig = figure('Name','Cat go by slandarer', 'Units','normalized', ...
    'Position',[.1,.1,.55,.8], 'WindowButtonDownFcn', @gogogo, 'WindowKeyPressFcn',@tbam);
ax = axes('Parent',fig, 'Color',[215,177,116]./255, 'PlotBoxAspectRatio',[1,1,1], ...
    'XLim',[1 - .6, 9 + .6], 'YLim',[1 - .6, 9 + .6], 'NextPlot','add', 'XColor','none', 'YColor','none');

% 绘制棋盘
tx = [1:9; 1:9; nan(1,9)]; ty = [ones(1,9); 9.*ones(1,9); nan(1,9)];
plot(ax, tx(:), ty(:), 'LineWidth',1, 'Color','k')
plot(ax, ty(:), tx(:), 'LineWidth',1, 'Color','k')
tx = [.9, .9, 9.1, 9.1, .9, .9];
ty = [.9, 9.1, 9.1, .9, .9, 9.1];
plot(ax, tx, ty, 'LineWidth',3, 'Color','k')
tt = linspace(0, 2*pi, 50); tx = cos(tt).*.08; ty = sin(tt).*.08;
fill(ax, tx + 3, ty + 3, [0,0,0]); fill(ax, tx + 7, ty + 3, [0,0,0])
fill(ax, tx + 3, ty + 7, [0,0,0]); fill(ax, tx + 7, ty + 7, [0,0,0])
% 数据初始化
goMat = zeros(9,9); turn = 1; emojiMap = zeros(0,3);
PMat{9,9} = []; LMat{9,9}=[];

GMat{1} = goMat;
EMat{1} = emojiMap;

    function gogogo(~, ~)
        xxyy = get(ax, 'CurrentPoint');
        pos = [round(xxyy(1,1)), round(xxyy(1,2))];
        pos(pos < 1) = 1; pos(pos > 9) = 9;

        if (goMat(pos(1), pos(2)) == 0)
            [SX, SY] = find(sign(goMat) == turn); SSet = [[SX, SY]; pos];
            [OX, OY] = find(sign(goMat) == -turn); OSet = [OX, OY];
            SNum = [0; unique(goMat(sign(goMat) == turn))];
            PSet = repmat(pos, [4,1]) + [-1,0;1,0;0,-1;0,1];
            ISSet = intersect(PSet, SSet, 'rows');
            IOSet = intersect(PSet, OSet, 'rows');
            flag = true;
            if size(IOSet,1) == 4
                flag = false;
            end
            newNum = min(setdiff(1:(max(abs(SNum))+1), abs(SNum)));
            % 落子
            switch size(ISSet,1)
                case 0 
                    goMat(pos(1), pos(2)) = turn*newNum;
                    drawStone(pos); 
                    emojiMap = [emojiMap; pos, turn*newNum];
                case 1
                    goMat(pos(1), pos(2)) = goMat(ISSet(1), ISSet(2));
                    drawStone(pos); drawStone(ISSet); 
                    emojiMap(emojiMap(:,3) == goMat(ISSet(1), ISSet(2)),:) = [pos, goMat(ISSet(1), ISSet(2))];
                case {2,3,4}
                    goMat(pos(1), pos(2)) = turn*newNum; 
                    drawStone(pos); 
                    for i = 1:size(ISSet,1)
                        emojiMap(emojiMap(:,3) == goMat(ISSet(i,1), ISSet(i,2)),:) = [];
                        goMat(goMat == goMat(ISSet(i,1), ISSet(i,2))) = turn*newNum;
                        drawStone([ISSet(i,1), ISSet(i,2)])
                    end
                    emojiMap = [emojiMap; pos, turn*newNum];
            end
            % 提对方子
            [EX, EY] = find(goMat == 0); ESet = [EX, EY];
            for i = 1:size(IOSet,1)
                tind = goMat(IOSet(i,1), IOSet(i,2));
                [tX, tY] = find(goMat == tind); tSet = [tX, tY];
                tN = size(tSet, 1);
                TSet = unique([tSet + repmat([-1,0], [tN,1]);
                        tSet + repmat([1,0], [tN,1]);
                        tSet + repmat([0,-1], [tN,1]);
                        tSet + repmat([0,1], [tN,1])],'rows');
                ITSet = intersect(TSet, ESet, 'rows');
                switch size(ITSet, 1)
                    case 0
                        flag = true;
                        emojiMap(emojiMap(:,3) == tind, :) = [];
                        for j = 1:size(tSet, 1)
                            goMat(tSet(j,1), tSet(j,2)) = 0;
                            delete(PMat{tSet(j,1), tSet(j,2)});
                            delete(LMat{tSet(j,1), tSet(j,2)});
                        end
                    case 1
                        emojiMap(emojiMap(:,3) == tind, :) = [IOSet(i,:), tind];
                end

            end
            % 提己方子
            [EX, EY] = find(goMat == 0); ESet = [EX, EY];
            tind = goMat(pos(1), pos(2));
            [tX, tY] = find(goMat == tind); tSet = [tX, tY];
            tN = size(tSet, 1);
            TSet = unique([tSet + repmat([-1,0], [tN,1]);
                        tSet + repmat([1,0], [tN,1]);
                        tSet + repmat([0,-1], [tN,1]);
                        tSet + repmat([0,1], [tN,1])],'rows');
            ITSet = intersect(TSet, ESet, 'rows');
            switch size(ITSet, 1)
                case 0
                    emojiMap(emojiMap(:,3) == tind, :) = [];
                    for j = 1:size(tSet, 1)
                        goMat(tSet(j,1), tSet(j,2)) = 0;
                        delete(PMat{tSet(j,1), tSet(j,2)});
                        delete(LMat{tSet(j,1), tSet(j,2)});
                    end
                case 1
                    emojiMap(emojiMap(:,3) == tind, :) = [pos, tind];
            end
            if flag 
                turn = - turn;
                GMat{end + 1} = goMat;
                EMat{end + 1} = emojiMap; 
            end
            drawEar()
            drawEmojiS()
        end   
    end

    function tbam(~, key)
        if strcmp(key.Key, 'b')
            if length(EMat) >= 2
                GMat(end) = [];
                EMat(end) = [];
                goMat = GMat{end};
                emojiMap = EMat{end};
                turn = - turn;
                for i = 1:9
                    for j = 1:9
                        drawStone([i,j])
                    end
                end
                drawEar()
                drawEmojiS()
            end
        end
    end


    % 绘制猫耳朵
    function drawEar(~, ~)
        tobj = findobj(ax, 'UserData', 'slan');
        for i = length(tobj):-1:1
            delete(tobj(i))
        end
        baseMat = goMat;
        ruMat = [[zeros(1,8);goMat(1:(end-1), 2:end)],zeros(9,1)];
        rdMat = [[goMat(2:end, 2:end);zeros(1,8)],zeros(9,1)];
        tmapru = (baseMat ~= ruMat) & (sign(baseMat) == sign(ruMat)) & (baseMat ~= 0);
        tmaprd = (baseMat ~= rdMat) & (sign(baseMat) == sign(rdMat)) & (baseMat ~= 0);


        tgoru = goMat(2:end, :);
        tgord = goMat(1:(end-1), :);
        tru = tmapru(2:end, :);
        trd = tmaprd(1:(end-1), :);
        tbool = tru & trd & (sign(tgoru) ~= sign(tgord));
        tru(tbool) = 0;
        trd(tbool) = 0;
        tmapru(2:end, :) = tru;
        tmaprd(1:(end-1), :) = trd;

        [rux, ruy] = find(tmapru == 1);
        for i = 1:length(rux)
            tturn = sign(goMat(rux(i), ruy(i))); C = [105,105,107]./255.*(tturn>0) +  [228,228,228]./255.*(tturn<0);
            fill(ax, [(rux(i)-1+.2), (rux(i)-.5-.03), (rux(i)-.45), (rux(i)-.2), (rux(i)-.5+.03), (rux(i)-1+.45)], ...
                     [(ruy(i)+1-.45), (ruy(i)+.5-.03), (ruy(i)+.2), (ruy(i)+.45), (ruy(i)+.5+.03), (ruy(i)+1-.2)], C, 'EdgeColor','none','UserData','slan')
            plot(ax, [(rux(i)-1+.2), (rux(i)-.5-.03), (rux(i)-.45)], [(ruy(i)+1-.45), (ruy(i)+.5-.03), (ruy(i)+.2)], 'Color','k', 'LineWidth',2,'UserData','slan')
            plot(ax, [(rux(i)-1+.45), (rux(i)-.5+.03), (rux(i)-.2)], [(ruy(i)+1-.2), (ruy(i)+.5+.03), (ruy(i)+.45)], 'Color','k', 'LineWidth',2,'UserData','slan')
        end
        [rdx, rdy] = find(tmaprd == 1);
        for i = 1:length(rdx)
            tturn = sign(goMat(rdx(i), rdy(i))); 
            C = [105,105,107]./255.*(tturn>0) +  [228,228,228]./255.*(tturn<0);
            fill(ax, [(rdx(i)+.2), (rdx(i)+.5-.03), (rdx(i)+1-.45), (rdx(i)+1-.2), (rdx(i)+.5+.03), (rdx(i)+.45)], ...
                     [(rdy(i)+.45), (rdy(i)+.5+.03), (rdy(i)+1-.2), (rdy(i)+1-.45), (rdy(i)+.5-.03), (rdy(i)+.2)], C, 'EdgeColor','none','UserData','slan')
            plot(ax, [(rdx(i)+.2), (rdx(i)+.5-.03), (rdx(i)+1-.45)], [(rdy(i)+.45), (rdy(i)+.5+.03), (rdy(i)+1-.2)], 'Color','k', 'LineWidth',2,'UserData','slan')
            plot(ax, [(rdx(i)+.45), (rdx(i)+.5+.03), (rdx(i)+1-.2)], [(rdy(i)+.2), (rdy(i)+.5-.03), (rdy(i)+1-.45)], 'Color','k', 'LineWidth',2,'UserData','slan')
        end

    end
    % 绘制表情
    function drawEmojiS(~,~)
        tobj = findobj(ax, 'UserData', 'emoji');
        for i = length(tobj):-1:1
            delete(tobj(i))
        end
        ttype = ones(size(emojiMap,1), 1);
        [EX, EY] = find(goMat == 0); ESet = [EX, EY];
        for i = 1:size(emojiMap,1)
            tind = emojiMap(i,3);
            [tX, tY] = find(goMat == tind); tSet = [tX, tY];
            tN = size(tSet, 1);
            TSet = unique([tSet + repmat([-1,0], [tN,1]);
                        tSet + repmat([1,0], [tN,1]);
                        tSet + repmat([0,-1], [tN,1]);
                        tSet + repmat([0,1], [tN,1])],'rows');
            ITSet = intersect(TSet, ESet, 'rows');
            if size(ITSet,1) == 1
                ttype(i) = 3;
                [OX, OY] = find(sign(goMat) == -sign(tind)); OSet = [OX, OY];
                IOOSet = intersect(TSet, OSet, 'rows');
                for j = 1:size(IOOSet, 1)
                    if ttype(emojiMap(:,3) == goMat(IOOSet(j,1),IOOSet(j,2))) ~= 3
                        ttype(emojiMap(:,3) == goMat(IOOSet(j,1),IOOSet(j,2))) = 2;
                    end
                end
            end
        end
        for i = 1:size(emojiMap,1)
            drawEmoji(emojiMap(i,1:2), ttype(i))
        end
    end
    function drawEmoji(pos, type)
        switch type
            case 1
                ttt1 = linspace(pi - pi/12, 2*pi - pi/12, 50);
                ttt2 = linspace(pi + pi/12, 2*pi + pi/12, 50);
                ttt3 = linspace(0, 2*pi, 50);
                ttx = [cos(ttt1).*.05-.05, cos(ttt2).*.05+.05] + pos(1);
                tty = [sin(ttt1).*.05, sin(ttt2).*.05] + pos(2) -.02;
                plot(ax, ttx, tty, 'Color','k', 'LineWidth',1.5, 'UserData','emoji')
                fill(ax, cos(ttt3).*.06 + pos(1) - .25,  sin(ttt3).*.06 + pos(2), [0,0,0], 'UserData','emoji')
                fill(ax, cos(ttt3).*.06 + pos(1) + .25,  sin(ttt3).*.06 + pos(2), [0,0,0], 'UserData','emoji')
            case 2
                ttt1 = linspace(0+pi/5, pi-pi/5, 50);
                ttt3 = linspace(0, 2*pi, 50);
                plot(ax, cos(ttt1).*.15 + pos(1),  sin(ttt1).*.12 + pos(2) - .25, 'Color','k', 'LineWidth',1.5, 'UserData','emoji')
                plot(ax, [.16,.35] + pos(1),  [.12,.16] + pos(2), 'Color','k', 'LineWidth',2, 'UserData','emoji')
                plot(ax, [-.16,-.35] + pos(1),  [.12,.16] + pos(2), 'Color','k', 'LineWidth',2, 'UserData','emoji')
                fill(ax, cos(ttt3).*.06 + pos(1) - .25,  sin(ttt3).*.06 + pos(2), [0,0,0], 'UserData','emoji')
                fill(ax, cos(ttt3).*.06 + pos(1) + .25,  sin(ttt3).*.06 + pos(2), [0,0,0], 'UserData','emoji')
            case 3
                ttt1 = linspace(0+pi/8, pi-pi/8, 50);
                ttx = cos(ttt1).*.22 + pos(1); ttx = [ttx, ttx(1)];
                tty = sin(ttt1).*.22 + pos(2) - .35; tty = [tty, tty(1)];
                ttt3 = linspace(0, 2*pi, 50);
                plot(ax, ttx, tty, 'Color','k', 'LineWidth',1.5, 'UserData','emoji')
                ttx = [.1,.1, nan, .16, .16, nan, .22, .22, nan, .28, .28, nan, .34, .34] + pos(1);
                tty = [.2,.4, nan, .14, .42, nan, .16, .36, nan, .01, .28, nan, .1, .25] + pos(2);
                plot(ax, ttx, tty, 'Color','k', 'LineWidth',1, 'UserData','emoji')
                ttx = [-.25,-.25, nan, -.3, -.3, nan, -.2, -.2] + pos(1);
                tty = [-.21,-.08, nan, -.18,-.06, nan, -.15,-.06] + pos(2);
                plot(ax, ttx, tty, 'Color','k', 'LineWidth',1, 'UserData','emoji')
                plot(ax, cos(ttt3).*.06 + pos(1) - .25,  sin(ttt3).*.06 + pos(2), 'Color','k', 'LineWidth',1.5, 'UserData','emoji')
                plot(ax, cos(ttt3).*.06 + pos(1) + .25,  sin(ttt3).*.06 + pos(2), 'Color','k', 'LineWidth',1.5, 'UserData','emoji')
        end
    end
    % 绘制棋子
    function drawStone(pos)
        delete(PMat{pos(1), pos(2)});
        delete(LMat{pos(1), pos(2)});
        if goMat(pos(1), pos(2)) ~= 0
            tturn = sign(goMat(pos(1), pos(2)));
            C = [105,105,107]./255.*(tturn>0) +  [228,228,228]./255.*(tturn<0);
            [SX, SY] = find(sign(goMat) == tturn); SSet = [SX, SY];
            PSet = repmat(pos, [4,1]) + [-1,0;1,0;0,-1;0,1];
            [~, IInd, ~] = intersect(PSet, SSet,'rows'); IInd = sort(IInd);
            if isempty(IInd)
                ttt = linspace(0,2*pi,100);
                ttx = cos(ttt).*.5 + pos(1);
                tty = sin(ttt).*.5 + pos(2);
                PMat{pos(1), pos(2)} = fill(ax, ttx, tty,C, 'EdgeColor','none');
                LMat{pos(1), pos(2)} = plot(ax, ttx, tty, 'Color','k', 'LineWidth',2);
            else
                switch length(IInd)
                    case 1
                        switch IInd
                            case 1
                                ttt = linspace(-pi/2, pi/2, 100);
                                ttx = [-.5, cos(ttt).*.5, -.5] + pos(1);
                                tty = [-.5, sin(ttt).*.5, .5] + pos(2);
                                PMat{pos(1), pos(2)} = fill(ax, ttx, tty, C, 'EdgeColor','none');
                                LMat{pos(1), pos(2)} = plot(ax, ttx, tty, 'Color','k', 'LineWidth',2);
                            case 2
                                ttt = linspace(pi/2, 3*pi/2, 100);
                                ttx = [.5, cos(ttt).*.5, .5] + pos(1);
                                tty = [.5, sin(ttt).*.5, -.5] + pos(2);
                                PMat{pos(1), pos(2)} = fill(ax, ttx, tty, C, 'EdgeColor','none');
                                LMat{pos(1), pos(2)} = plot(ax, ttx, tty, 'Color','k', 'LineWidth',2);
                            case 3
                                ttt = linspace(0, pi, 100);
                                ttx = [.5, cos(ttt).*.5, -.5] + pos(1);
                                tty = [-.5, sin(ttt).*.5, -.5] + pos(2);
                                PMat{pos(1), pos(2)} = fill(ax, ttx, tty, C, 'EdgeColor','none');
                                LMat{pos(1), pos(2)} = plot(ax, ttx, tty, 'Color','k', 'LineWidth',2);
                            case 4
                                ttt = linspace(pi, 2*pi, 100);
                                ttx = [-.5, cos(ttt).*.5, .5] + pos(1);
                                tty = [.5, sin(ttt).*.5, .5] + pos(2);
                                PMat{pos(1), pos(2)} = fill(ax, ttx, tty, C, 'EdgeColor','none');
                                LMat{pos(1), pos(2)} = plot(ax, ttx, tty, 'Color','k', 'LineWidth',2);
                        end
                    case 2
                        switch true
                            case all(IInd == [1;2])
                                PMat{pos(1), pos(2)} = fill(ax, pos(1) + [-.5, .5, .5, -.5],...
                                    pos(2) + [-.5, -.5, .5, .5], C, 'EdgeColor','none');
                                LMat{pos(1), pos(2)} = plot(ax, pos(1) + [-.5, .5, nan, .5, -.5], ...
                                    pos(2) + [-.5, -.5, nan .5, .5], 'Color','k', 'LineWidth',2);
                            case all(IInd == [3;4])
                                PMat{pos(1), pos(2)} = fill(ax, pos(1) + [-.5, -.5, .5, .5],...
                                    pos(2) + [-.5, .5, .5, -.5], C, 'EdgeColor','none');
                                LMat{pos(1), pos(2)} = plot(ax, pos(1) + [-.5, -.5, nan .5, .5], ...
                                    pos(2) + [-.5, .5, nan, .5, -.5], 'Color','k', 'LineWidth',2);
                            case all(IInd == [1;3])
                                ttt = linspace(0, pi/2, 100);
                                ttx = [-.5, .5, cos(ttt).*.5, -.5] + pos(1);
                                tty = [-.5, -.5, sin(ttt).*.5, .5] + pos(2);
                                PMat{pos(1), pos(2)} = fill(ax, ttx, tty, C, 'EdgeColor','none');
                                LMat{pos(1), pos(2)} = plot(ax, ttx(2:end), tty(2:end), 'Color','k', 'LineWidth',2);
                            case all(IInd == [1;4])
                                ttt = linspace(3*pi/2, 2*pi, 100);
                                ttx = [-.5, -.5, cos(ttt).*.5, .5] + pos(1);
                                tty = [.5, -.5, sin(ttt).*.5, .5] + pos(2);
                                PMat{pos(1), pos(2)} = fill(ax, ttx, tty, C, 'EdgeColor','none');
                                LMat{pos(1), pos(2)} = plot(ax, ttx(2:end), tty(2:end), 'Color','k', 'LineWidth',2);
                            case all(IInd == [2;3])
                                ttt = linspace(pi/2, pi, 100);
                                ttx = [.5, .5, cos(ttt).*.5, -.5] + pos(1);
                                tty = [-.5, .5, sin(ttt).*.5, -.5] + pos(2);
                                PMat{pos(1), pos(2)} = fill(ax, ttx, tty, C, 'EdgeColor','none');
                                LMat{pos(1), pos(2)} = plot(ax, ttx(2:end), tty(2:end), 'Color','k', 'LineWidth',2);
                            case all(IInd == [2;4])
                                ttt = linspace(pi, 3*pi/2, 100);
                                ttx = [.5, -.5, cos(ttt).*.5, .5] + pos(1);
                                tty = [.5, .5, sin(ttt).*.5, -.5] + pos(2);
                                PMat{pos(1), pos(2)} = fill(ax, ttx, tty, C, 'EdgeColor','none');
                                LMat{pos(1), pos(2)} = plot(ax, ttx(2:end), tty(2:end), 'Color','k', 'LineWidth',2);
                        end
                    case 3
                        ttx = [-.5, .5, .5, -.5] + pos(1);
                        tty = [-.5, -.5, .5, .5] + pos(2);
                        PMat{pos(1), pos(2)} = fill(ax, ttx, tty, C, 'EdgeColor','none');
                        switch true
                            case all(IInd == [2;3;4]), ttx = [-.5, -.5] + pos(1); tty = [-.5, .5] + pos(2);
                            case all(IInd == [1;3;4]), ttx = [.5, .5] + pos(1); tty = [-.5, .5] + pos(2);
                            case all(IInd == [1;2;4]), ttx = [-.5, .5] + pos(1); tty = [-.5, -.5] + pos(2);
                            case all(IInd == [1;2;3]), ttx = [-.5, .5] + pos(1); tty = [.5, .5] + pos(2);
                        end
                        LMat{pos(1), pos(2)} = plot(ax, ttx, tty, 'Color','k', 'LineWidth',2);
                    case 4
                        ttx = [-.5, .5, .5, -.5] + pos(1);
                        tty = [-.5, -.5, .5, .5] + pos(2);
                        PMat{pos(1), pos(2)} = fill(ax, ttx, tty, C, 'EdgeColor','none');
                        LMat{pos(1), pos(2)} = [];
                end
            end
        end

    end
end
相关推荐
rit84324994 小时前
基于偏振物理模型的水下图像去雾MATLAB实现
开发语言·matlab
bu_shuo4 小时前
MATLAB R2025b中消失的Specialized Power Systems库
matlab·simulink·sps库
jllllyuz4 小时前
ANPC三电平逆变器损耗计算的MATLAB实现
开发语言·matlab·php
aini_lovee4 小时前
基于MATLAB Simulink的定轴齿轮与行星齿轮仿真模型
开发语言·matlab
leo__5204 小时前
基于模糊控制的MATLAB避障算法实现
算法·matlab·unity
英英_14 小时前
MATLAB数值计算基础教程
数据结构·算法·matlab
jllllyuz15 小时前
基于子集模拟的系统与静态可靠性分析及Matlab优化算法实现
算法·matlab·概率论
yugi98783816 小时前
基于遗传算法优化主动悬架模糊控制的Matlab实现
开发语言·matlab
yugi98783817 小时前
MATLAB的多层感知器(MLP)与极限学习机(ELM)实现
开发语言·matlab