迷宫程序是新手常用的练习算法之一,迷宫生成与循迹的快慢取决于所建立的模型的好坏。本文介绍一种数学模型,用以自动生成(任意规模)的迷宫并可视化寻找最优出路。
废话不多说,都在代码里,原理很简单,可以仔细阅读代码
效果图如下:(迷宫大小可自行设置)
本文代码在MATLAB2016码出来的,若有问题请检查函数的使用
%%%%%***************迷宫程序*************************
%%%****(包括自动生成迷宫以及可视化寻找出路)************
clc
close all
clear all
%%%迷宫规模ak X ak,并规定寻迹时行走速度
ssss=0.02;%%速度
ak=60;%%迷宫规模(ak*ak)
CS12=1;%%是否展示循迹过程(1:是,其他:否)
%%%*****************主程序***************************
C=[1,ak];%%出口
R=[ak,1];%%入口
x0=[0 ak ak 0 0];
y0=[0 0 ak ak 0];
plot(x0,y0)%%画出基本画框
hold on
C1=[C(1)-1,C(1),C(1),C(1)-1,C(1)-1
C(2)-1,C(2)-1,C(2),C(2),C(2)-1];
fill(C1(1,:),C1(2,:),'g')
hold on
R1=[R(1)-1,R(1),R(1),R(1)-1,R(1)-1
R(2)-1,R(2)-1,R(2),R(2),R(2)-1];
fill(R1(1,:),R1(2,:),'R')%%填充出入口
set(gcf,'Unit','normalized','Position',[0,0,0.6,1])
hold on
axis([0,ak,0,ak]);%%发图大小
ok=1;
% for mmm=1:1
% % while ok~=0
aaaa=fix(rand(ak,ak)*4);%%随机生成墙体矩阵
bbbb=tril(aaaa,-1)+triu(aaaa',0);
x1=bbbb;
%%%强行约束出入口,主要是保证能够进出 出入口
x1(R(1),R(2))=3;
x1(R(1),R(2)+1)=3;
x1(R(1)-1,R(2))=2;
x1(R(1)-1,R(2)+1)=x1(R(1)-1,R(2)+2);
x1(C(1),C(2))=0;
x1(C(1),C(2)-1)=1;
x1(C(1)+1,C(2))=0;
x1(C(1)+1,C(2)-1)=x1(C(1)+2,C(2)-1);
%%%for循环内部的作用为:提高迷宫的可解性,但是会缺少灵魂
% for i=3:length(x1)-2
% % x1(i,length(x1)-i+1)=2;
% % x1(i-1,length(x1)-i)=1;
% % x1(i-1,length(x1)-i+2)=0;
% x1(i,length(x1)-i+2)=x1(i-1,length(x1)-i+1)+2;
% % x1(i,length(x1)-i)=x1(i+1,length(x1)-i+1)+1;
% x1(i+1,length(x1)-i+1)=x1(i-2,length(x1)-i+1)+0;
% % x1(i-1,length(x1)-i+1)=x1(i+2,length(x1)-i+1)+1;
% end
k=length(x1(1,:));
%%%画隔板******并记录每面墙的数据LJ ****最终将墙体的全局信息存入矩阵SD****
for i=1:k
for j=1:k
switch x1(i,j)+1
case 1
plot([i,i-1],[j,j],'color','b','linewidth',1)
LJ(2*i,2*j+1)=1;
case 2
plot([i-1,i-1],[j,j-1],'color','b','linewidth',1)
LJ(2*i-1,2*j)=1;
case 3
plot([i,i-1],[j-1,j-1],'color','b','linewidth',1)
LJ(2*i,2*j-1)=1;
case 4
plot([i,i],[j,j-1],'color','b','linewidth',1)
LJ(2*i+1,2*j)=1;
end
end
end
LJ(1,:)=ones;
LJ(:,1)=ones;
LJ(2*k+1,:)=ones;
LJ(:,2*k+1)=ones;
SD=LJ;
SD(R)=SD(R)+1;
SD(C)=SD(C)+1;
xx=R(1);
yy=R(2);
h1=plot(xx,yy,'color','g','linewidth',3);
hold on
%%寻找出路部分*********上下左右的循迹方向具有不同优先级
aac=0;
GJ=zeros(2,1e3);
while xx~=C(1)||yy~=C(2)
az=[SD(2*xx,2*yy+1),SD(2*xx-1,2*yy),SD(2*xx,2*yy-1),SD(2*xx+1,2*yy)];
if min(az)<1
wz=min(find(az==min(az)));
else
wz=[];
end
if isempty(wz)==1
error('抱歉,已无路可走')
close all
clear
else
%%%选择移动方向(优先级依次为上,左,下,右)**
switch wz
case 1
xx1=xx;yy1=yy+1;
case 2
xx1=xx-1;yy1=yy;
case 3
xx1=xx;yy1=yy-1;
case 4
xx1=xx+1;yy1=yy;
end
aac=aac+1;
GJ(:,aac)=[xx1
yy1];%%%记录轨迹
%%%方向已选定为xx1,yy1*************
end
%以下的一个set和四个plot以及pause作用均是体现内部循迹原理的作用
if CS12==1
set(h1,'Xdata',[xx-0.5,xx1-0.5],'Ydata',[yy-0.5,yy1-0.5])
hold on
km=1/3;
switch wz
case 1
plot([xx,xx-1],[yy,yy],'-.','color','r','linewidth',1)
SD(2*xx,2*yy+1)=SD(2*xx,2*yy+1)+km;
case 2
plot([xx-1,xx-1],[yy,yy-1],'-.','color','r','linewidth',1)
SD(2*xx-1,2*yy)=SD(2*xx-1,2*yy)+km;
case 3
plot([xx,xx-1],[yy-1,yy-1],'-.','color','r','linewidth',1)
SD(2*xx,2*yy-1)=SD(2*xx,2*yy-1)+km;
case 4
plot([xx,xx],[yy,yy-1],'-.','color','r','linewidth',1)
SD(2*xx+1,2*yy)=SD(2*xx+1,2*yy)+km;
end
xx=xx1;
yy=yy1;
pause(0.01)
else
km=1/3;
switch wz
case 1
SD(2*xx,2*yy+1)=SD(2*xx,2*yy+1)+km;
case 2
SD(2*xx-1,2*yy)=SD(2*xx-1,2*yy)+km;
case 3
SD(2*xx,2*yy-1)=SD(2*xx,2*yy-1)+km;
case 4
SD(2*xx+1,2*yy)=SD(2*xx+1,2*yy)+km;
end
xx=xx1;
yy=yy1;
end
% pause(ssss/100)
end
%%**************寻迹之后规划最优路径***********
sl=min(find(GJ(1,:)==0))-1;
GJ(:,sl+1:end)=[];
% GG=GJ;
% [b,location] = unique(GG.','rows','first');
% res = sortrows([location,b]);
% GJ=res(:,2:size(res,2)).'%%%此上三句是消除重复行走的位置
% hold off
for mmk=1:length(GJ(1,:))-1
for mk1=mmk+1:length(GJ(1,:))
if GJ(:,mmk)==GJ(:,mk1)
GJ(:,mmk:mk1-1)=zeros(2,mk1-mmk);
end
end
end
GJ(:,find(GJ(1,:)==0))=[];
GJ=[R.',GJ];
for mk=1:length(GJ(1,:))-1
plot([GJ(1,mk)-0.5,GJ(1,mk+1)-0.5],[GJ(2,mk)-0.5,GJ(2,mk+1)-0.5],'color','g')
hold on
if CS12==1
pause(ssss)
else
pause(ssss/2)
end
end