Matlab利用prim算法实现迷宫的生成

 更新时间:2022年10月13日 15:12:16   作者:slandarer  
普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。本文将利用prim算法迷宫生成及其艺术渲染,感兴趣的可以了解一下

最近比较忙更新频率也慢了下来,今天带来一个比较有趣的可视化,基于prim算法的迷宫生成并用距离生成图片:

我通过各种向量化编程编写了一个迷宫生成函数,由于代码不是很短因此放在最后面展示代码,以下展示如果将最前面的参数进行改变会有啥效果。

代码使用

迷宫生成

迷宫生成就是用的非常简单的prim算法,大体就是不断的在已经开过门的房间四周随机选择紧挨着的房间,直到所有房间被开过。我的代码编写是专门弄了五个矩阵,一个存已经到过的房间,另外四个分别存上下左右打开过的围墙。

如果代码最前面的基础信息设置为:

% 地图基础信息设置
mazeSize=[30,30];
SPos=[2,5];
showMap=true;
showSurf=false;

就意味着绘制30x30个房间,从第二行第五个房间开始开门,展示迷宫但是不展示距离映射。

当然设置其他大小和其他起点也可以:

映射图

将到起点的距离映射为颜色,只需要将前面的showSurf更改为true:

% 地图基础信息设置
mazeSize=[30,30];
SPos=[2,5];
showMap=true;
showSurf=true;

当然如果设置的地图较大,建议将showMap设置为false,不然绘制的太慢了:

mazeSize=[200,200];
SPos=[50,50];
showMap=false;
showSurf=true;

当然如果把74多行的colormap改成其他颜色,比如pink、bone、turbo、colorcube:

当然colormap可以自己设置的更复杂:

% 自定义色带
if 1
Cmap=[89,214,179
140,181,195
177,156,206
241,189,239
215,193,244
178,199,253
140,189,234
145,166,229
106,85,202]./255;
Ci=1:size(Cmap,1);Cq=linspace(1,size(Cmap,1),300);
Cmap=[interp1(Ci,Cmap(:,1),Cq,'linear')',...
     interp1(Ci,Cmap(:,2),Cq,'linear')',...
     interp1(Ci,Cmap(:,3),Cq,'linear')'];
colormap(Cmap)
end

多起点

值得一提的是,多个起点也是支持的!!

% 地图基础信息设置
mazeSize=[30,30];
SPos=[2,5;20,15];
showMap=true;
showSurf=true;

依旧可以设置颜色和更大的地图:

当然不建议将大小设置为300x300以上,???什么玩意这么香????嗷原来是我的电脑!!

完整代码

function primMaze
% @author : slandarer
% 公众号  : slandarer随笔
% 知乎    : 已由hikari更名slandarer

% 地图基础信息设置
mazeSize=[50,50];
SPos=[2,5];
showMap=true;
showSurf=true;

% 初始化可达迷宫及上下左右围墙矩阵
mazeMat=ones(mazeSize);
mazeMat(sub2ind(mazeSize,SPos(:,1),SPos(:,2)))=0;
zerosMat=zeros(mazeSize);
disMat=zeros(mazeSize);
[UMat,DMat,LMat,RMat]=...
    deal(ones(mazeSize),ones(mazeSize),ones(mazeSize),ones(mazeSize));

if showMap
    wallHdl=drawMap(UMat,DMat,LMat,RMat);
end

while any(any(mazeMat))
    % 找到全部已经走到过且周围至少有一个门的房间
    UMazeMat=zerosMat;UMazeMat(2:end,:)=mazeMat(1:end-1,:);
    DMazeMat=zerosMat;DMazeMat(1:end-1,:)=mazeMat(2:end,:);
    LMazeMat=zerosMat;LMazeMat(:,2:end)=mazeMat(:,1:end-1);
    RMazeMat=zerosMat;RMazeMat(:,1:end-1)=mazeMat(:,2:end);
    maze4Mat=UMazeMat+DMazeMat+LMazeMat+RMazeMat;
    [acRow,acCol]=find(mazeMat==0&maze4Mat>0);
    % 随机选择一个当前已经走到过的房间
    tempInd=randi(size(acRow,1),[1,1]);
    tempRow=acRow(tempInd);
    tempCol=acCol(tempInd);
    % 删掉地图外房间位置和不可达房间位置
    nextPos=[tempRow,tempCol]+[-1,0;1,0;0,-1;0,1];
    nextPos(nextPos(:,1)<1,:)=[];
    nextPos(nextPos(:,2)<1,:)=[];
    nextPos(nextPos(:,1)>mazeSize(1),:)=[];
    nextPos(nextPos(:,2)>mazeSize(2),:)=[];
    nextBool=mazeMat(sub2ind(mazeSize,nextPos(:,1),nextPos(:,2)))>0;
    nextPos=nextPos(nextBool,:);
    % 随机选择下一个房间
    nextInd=randi(size(nextPos,1),[1,1]);
    nextRow=nextPos(nextInd,1);
    nextCol=nextPos(nextInd,2);
    mazeMat(nextRow,nextCol)=0;
    disMat(nextRow,nextCol)=disMat(tempRow,tempCol)+1;
    % 打破墙壁
    switch true
        case isequal([nextRow,nextCol]-[tempRow,tempCol],[-1,0])
            UMat(tempRow,tempCol)=0;DMat(nextRow,nextCol)=0;
        case isequal([nextRow,nextCol]-[tempRow,tempCol],[1,0])
            DMat(tempRow,tempCol)=0;UMat(nextRow,nextCol)=0;
        case isequal([nextRow,nextCol]-[tempRow,tempCol],[0,-1])
            LMat(tempRow,tempCol)=0;RMat(nextRow,nextCol)=0;
        case isequal([nextRow,nextCol]-[tempRow,tempCol],[0,1])
            RMat(tempRow,tempCol)=0;LMat(nextRow,nextCol)=0;
    end
    % 用来显示地迷宫的代码
    if showMap
    refreshMap(wallHdl,UMat,DMat,LMat,RMat)
    drawnow
    end
end
% =========================================================================
% 绘制颜色映射图
if showSurf
sax=gca;hold on
[sM,sN]=size(UMat);
sax.XLim=[0,sN]+.5;
sax.YLim=[0,sM]+.5;
sax.DataAspectRatio=[1,1,1];
surf(flipud(disMat),'EdgeColor','none')
colormap(pink)

% 自定义色带
if 0
Cmap=[89,214,179
140,181,195
177,156,206
241,189,239
215,193,244
178,199,253
140,189,234
145,166,229
106,85,202]./255;
Ci=1:size(Cmap,1);Cq=linspace(1,size(Cmap,1),300);
Cmap=[interp1(Ci,Cmap(:,1),Cq,'linear')',...
     interp1(Ci,Cmap(:,2),Cq,'linear')',...
     interp1(Ci,Cmap(:,3),Cq,'linear')'];
colormap(Cmap)
end
end
% =========================================================================
% CODE: test drawMap
% UMat(2,3)=0;
% DMat(1,3)=0;
% drawMap(UMat,DMat,LMat,RMat)
    function wallHdl=drawMap(UMat,DMat,LMat,RMat)
        ax=gca;hold on
        [M,N]=size(UMat);
        ax.XLim=[0,N]+.5;
        ax.YLim=[0,M]+.5;
        ax.DataAspectRatio=[1,1,1];
        % 绘制上方围墙
        [Y,X]=find(UMat);Y=M+1-Y;
        X=[X.'+[.5;-.5];nan.*(ones(1,length(X)))];
        Y=[Y.'+[.5;.5];nan.*(ones(1,length(Y)))];
        wallHdl{1}=plot(X(:),Y(:),'LineWidth',1,'Color','k');
        % 绘制下方围墙
        [Y,X]=find(DMat);Y=M+1-Y;
        X=[X.'+[.5;-.5];nan.*(ones(1,length(X)))];
        Y=[Y.'+[-.5;-.5];nan.*(ones(1,length(Y)))];
        wallHdl{2}=plot(X(:),Y(:),'LineWidth',1,'Color','k');
        % 绘制左侧围墙
        [Y,X]=find(LMat);Y=M+1-Y;
        X=[X.'+[-.5;-.5];nan.*(ones(1,length(X)))];
        Y=[Y.'+[.5;-.5];nan.*(ones(1,length(Y)))];
        wallHdl{3}=plot(X(:),Y(:),'LineWidth',1,'Color','k');
        % 绘制右侧围墙
        [Y,X]=find(RMat);Y=M+1-Y;
        X=[X.'+[.5;.5];nan.*(ones(1,length(X)))];
        Y=[Y.'+[.5;-.5];nan.*(ones(1,length(Y)))];
        wallHdl{4}=plot(X(:),Y(:),'LineWidth',1,'Color','k');
    end
% -------------------------------------------------------------------------
    function refreshMap(wallHdl,UMat,DMat,LMat,RMat)
        [M,~]=size(UMat);
        % 绘制上方围墙
        [Y,X]=find(UMat);Y=M+1-Y;
        X=[X.'+[.5;-.5];nan.*(ones(1,length(X)))];
        Y=[Y.'+[.5;.5];nan.*(ones(1,length(Y)))];
        wallHdl{1}.XData=X(:);
        wallHdl{1}.YData=Y(:);
        % 绘制下方围墙
        [Y,X]=find(DMat);Y=M+1-Y;
        X=[X.'+[.5;-.5];nan.*(ones(1,length(X)))];
        Y=[Y.'+[-.5;-.5];nan.*(ones(1,length(Y)))];
        wallHdl{2}.XData=X(:);
        wallHdl{2}.YData=Y(:);
        % 绘制左侧围墙
        [Y,X]=find(LMat);Y=M+1-Y;
        X=[X.'+[-.5;-.5];nan.*(ones(1,length(X)))];
        Y=[Y.'+[.5;-.5];nan.*(ones(1,length(Y)))];
        wallHdl{3}.XData=X(:);
        wallHdl{3}.YData=Y(:);
        % 绘制右侧围墙
        [Y,X]=find(RMat);Y=M+1-Y;
        X=[X.'+[.5;.5];nan.*(ones(1,length(X)))];
        Y=[Y.'+[.5;-.5];nan.*(ones(1,length(Y)))];
        wallHdl{4}.XData=X(:);
        wallHdl{4}.YData=Y(:);
    end
end

以上就是Matlab利用prim算法实现迷宫的生成的详细内容,更多关于Matlab prim算法生成迷宫的资料请关注脚本之家其它相关文章!

相关文章

  • C语言用栈实现十进制转换为二进制的方法示例

    C语言用栈实现十进制转换为二进制的方法示例

    这篇文章主要介绍了C语言用栈实现十进制转换为二进制的方法,结合实例形式分析了C语言栈的定义及进制转换使用技巧,需要的朋友可以参考下
    2017-06-06
  • C++vector的用法你都知道嘛

    C++vector的用法你都知道嘛

    这篇文章主要为大家详细介绍了C++中vector的用法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • Qt实现棋盘游戏

    Qt实现棋盘游戏

    这篇文章主要为大家详细介绍了Qt实现棋盘游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • C语言控制台实现字符飞机大战

    C语言控制台实现字符飞机大战

    这篇文章主要为大家详细介绍了C语言控制台实现字符飞机大战,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • c++中临时变量不能作为非const的引用参数的方法

    c++中临时变量不能作为非const的引用参数的方法

    下面小编就为大家带来一篇c++中临时变量不能作为非const的引用参数的方法。小编觉得挺不错的现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • C语言制作贪吃蛇小游戏

    C语言制作贪吃蛇小游戏

    这篇文章主要为大家详细介绍了C语言制作贪吃蛇小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • C/C++ 双链表之逆序的实例详解

    C/C++ 双链表之逆序的实例详解

    这篇文章主要介绍了C/C++ 双链表之逆序的实例详解的相关资料,需要的朋友可以参考下
    2017-07-07
  • C语言中强制类型转换的常见方法

    C语言中强制类型转换的常见方法

    强制类型转换是一种将一个数据类型转换为另一个数据类型的方法,这篇文章主要为大家整理了C语言中强制类型转换的方法,需要的可以参考一下
    2023-05-05
  • 关于统计数字问题的算法

    关于统计数字问题的算法

    本文介绍了统计数字问题的算法,计算出书的全部页码中分别用到多少次数字0,1,2,3,.....9,并有每一步的解题思路,需要的朋友可以参考下
    2015-08-08
  • 深入浅析C/C++语言结构体指针的使用注意事项

    深入浅析C/C++语言结构体指针的使用注意事项

    这篇文章主要介绍了C/C++语言结构体指针的使用,大家都知道指针在32位系统占用4Byte,在64位系统占用8Byte,下面看下c语言代码例子
    2021-12-12

最新评论