图的遍历迷宫算法浅析详解.docx
- 文档编号:901445
- 上传时间:2022-10-13
- 格式:DOCX
- 页数:18
- 大小:326.11KB
图的遍历迷宫算法浅析详解.docx
《图的遍历迷宫算法浅析详解.docx》由会员分享,可在线阅读,更多相关《图的遍历迷宫算法浅析详解.docx(18页珍藏版)》请在冰豆网上搜索。
图的遍历迷宫算法浅析详解
1.引言
在平常的游戏中,我们常常会碰到随机生成的地图。
这里我们就来看看一个简单的随机迷宫是如何生成。
2.迷宫描述
随机生成一个m*n的迷宫,可用一个矩阵maze[m][n]来表示,如图:
图1.1图1.2
这里是两个迷宫的例子,其中“■”表示障碍物(Obstacleblock)。
以图1.1迷宫为例,我们可用一个9*9的矩阵来表示:
111111111
000000001
111111101
100000101
101111101
101000001
101011111
100000000
111111111
(矩阵中1表示是障碍物,0表示可以行走)
3、迷宫生成算法
(蓝色表示可以行走,棕色表示是墙壁)
图3.1
如图3.1所示为迷宫的初始化情形,迷宫如果除去其迷宫的外围框架就是一个7*7的矩阵,如果要生成一个完整的迷宫,那么就要遍历完图3.1所示的每一个可以行走的点,其中遍历的点也包含了入口和出口,如果每一个点都遍历完了就会生成一棵完整的遍历树,这棵遍历树包含了入口和出口所以这颗树所描述的迷宫是有解的(即:
入口到出口时连通的。
)图3.2就表示图1.1迷宫遍历所得到的遍历树,树包含了入口和出口所以此迷宫有解。
图3.2
图3.3
图3.3表示的是图3.2进一步的处理后得到的最终迷宫图,就是在图3.2的基础上把遍历树上的是墙壁的元素置为可行走的元素。
3.1元素的遍历
图3.1.1描述了各个遍历点的连接关系其中1元素为起始遍历点,49元素为终点遍历点我们声明一个mazepoint类用来描述每一个遍历点xtemp表示当前点在数组中的x坐标,ytemp表示当前点在数组中的y坐标,定义为mazepoint对象的next用来链表一个点的地址last用来链表上一个地址。
图3.1.1
声明了两个mazepoint的变量head和tail用于存储迷宫的链表的头地址和尾地址由于在迷宫刚刚开始的时候初始化元素是第一个所以头尾是相同的在主函数中把head赋值给了p1,(p1是我们声明的一个临时存储的变量;p1和p2用于新的链表元素生成)
如图3.1.2所示元素1它连接到元素3和元素15,所以它可以遍历这两个元素,假设遍历的方向是随机的,如果第一次现在向右遍历那么元素3就被遍历并把它标志为flag(flag表示已经遍历过了不容许再次遍历),所以元素1和元素3都标志位flag说明在其它元素想遍历它们的时候是不能再次被遍历了。
这就有可能会遍历成一棵完整的树。
图3.1.2
如图3.1.3所示图1.1迷宫在生成时前13步,据图我们可知在第13步的时候遍历到元素19,但是元素19周围的点都已经遍历过但同时还有其它元素还没有遍历到,所以要后退到上一个遍历过的元素判断是否有遍历的方向,所以链表到元素17,但是此元素也没有可遍历的方向所以要一直往上链表直到链表到某一个可以重新遍历的点为之。
图3.1.3
图3.1.4是往上链表的示意图直到链表到元素45发现此元素拥有可遍历的方向,所以又重新往下建立新的链表,即元素47
图3.1.4
图3.1.5是最终遍历完后的遍历路径,此时只要沿着遍历的方向把相应的“墙”拆掉就可以生成一个无外框的迷宫并且只能生成奇数行和奇数列的迷宫。
图3.1.5
图3.1.6是程序生成得33*33的迷宫
图3.1.6
4、编程思路
5、源代码
#include
#include
usingstd:
:
cout;
usingstd:
:
cin;
usingstd:
:
endl;
#defineRow33//用于定义迷宫的行必须为奇数,否则不能遍历到所以的点
#defineCol33//用于定义迷宫的列必须为奇数,否则不能遍历到所以的点
#defineflag1//点的标志位,如果找到符合条件的点就把它置为flag,只要某一个点置位为flag就不能再次被访问;
intx_row=0;//迷宫的起始点位置的x坐标
inty_col=0;//迷宫的起始点位置的y坐标
intLeft=0;//初始化向左的方向标志位Left
intRight=0;//初始化向右的方向标志位Right
intUp=0;//初始化向上的方向标志位Up
intDwon=0;//初始化向下的方向标志位Dwon
intpointcount=((Row+1)*(Col+1)/4-1);//初始化要遍历的点数,(因为第一个点不要遍历了,所以总点数要减去1)
intget_count();//定义可以获得某一个点可以行走的方向数的函数
classmazepoint//定义一个类用于存放每一个遍历点的坐标
{
public:
intxtemp;//用于存放一个遍历点的x坐标
intytemp;//用于存放一个遍历点的y坐标
mazepoint*next;//用于存放一个遍历点的下一个遍历点的地址
mazepoint*last;//用于存放一个遍历点的上一个遍历点的地址
};
mazepoint*p1;
mazepoint*p2;
mazepoint*head=NULL;//初始化头由于没有指向如何位置所以赋值为NULL
mazepoint*tail=NULL;//初始化尾由于没有指向如何位置所以赋值为NULL
intmazemap[Row][Col]=//初始化迷宫地图数组
{
1
};
intmain()
{
p1=newmazepoint;//声明一片内存空间
p1->xtemp=0;//初始化类元素x坐标
p1->ytemp=0;//初始化类元素y坐标
p1->last=NULL;//初始类只有一个元素没有前一个元素,链接到别的元素所以它的的上一个遍历点位空NULL
head=p1;//把链表的头地址赋值给p1
tail=p1;//刚刚开始没有其它元素所以把链表的尾地址也是p1
intmazenum=0;//用于统计遍历的次数
srand(time(0));//用当前时间做随机种子数
while(pointcount)//如果没有遍历完所有的点就继续遍历,以确保每一次的随机数都不一样
{
intrdNo=rand();//获得随机数
intRandtemp;//定义一个变量,用于存储处理后的随机数
inttempflag;//定义一个变量,用于存储某一个点可以行走的方向数
tempflag=get_count();//获得某一个点可以行走的方向数
if(tempflag!
=0)//如果某一个点可以行走就处理随机数然后随机选择行走的方向
Randtemp=rdNo%tempflag;//根据返回的可以行走的方向提供行走方向数
else
{
Randtemp=NULL;//如果不能行走就赋值为NULL
}
cout<<"电脑随机数为:
"< Randtemp+=1;//加1是为了和定义的方向Left,Right,Up,Dwon相匹配 cout<<"随机数为: "< if(tempflag! =0)//如果可以行走 { p2=p1; p1->xtemp=x_row;//保存当前点的x坐标 p1->ytemp=y_col;//保存当前点的y坐标 p1=newmazepoint;//声明内存 p2->next=p1;//前一个遍历点链表到下一个点的地址 p1->last=p2;//后一个遍历点链表到上一个点的地址 p1->next=NULL;//新生产的点没有链表到下一个点所以设为NULL。 (新产生的点是链表的最后一个点) if(Randtemp==Left&&mazemap[x_row][y_col-2]! =flag)//判断左边是否可以走如果可以走就不为;flagRandtemp==Left表示随机数等于Left { //*********************************************************************** //↓mazemap[x_row][y_col];新遍历到的位置* //■□▲←上一次确定的位置* //↑mazemap[x_row][y_col+1];新遍历到位置的相同方向的临近元素* //*********************************************************************** y_col-=2;//如果可以左走就要把对应的坐标也要改变;也就是行值减2 mazemap[x_row][y_col]=flag;//把遍历到的新的迷宫地图元素也要置flag mazemap[x_row][y_col+1]=flag;//把遍历到的新的迷宫地图元素相同方向的临近元素也要置flag --pointcount;//遍历到新的一个点,那么遍历点的总数pointcount减1 cout<<"IchoiceLeft"< } elseif(Randtemp==Right&&mazemap[x_row][y_col+2]! =flag)//判断右边是否可以走如果可以走就不为;flagRandtemp==Right表示随机数等于Right { //*********************************************************************************** //↓mazemap[x_row][y_col];新遍历到的位置* //上一次确定的位置→▲□■* //↑mazemap[x_row][y_col-1];新遍历到位置的相同方向的临近元素* //*********************************************************************************** y_col+=2;//如果可以右走就要把对应的坐标也要改变;也就是行值加2 mazemap[x_row][y_col]=flag;//把遍历到的新的迷宫地图元素也要置flag mazemap[x_row][y_col-1]=flag;//把遍历到的新的迷宫地图元素相同方向的临近元素也要置flag --pointcount;//遍历到新的一个点,那么遍历点的总数pointcount减1 cout<<"IchoiceRight"< }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 遍历 迷宫 算法 浅析 详解
![提示](https://static.bdocx.com/images/bang_tan.gif)