目录 代码使用 迷宫生成 映射图 多起点 完整代码 最近比较忙更新频率也慢了下来,今天带来一个比较有趣的可视化,基于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算法生成迷宫的资料请关注自由互联其它相关文章!