1、3、迷宫生成算法(蓝色表示可以行走,棕色表示是墙壁) 图3.1如图3.1所示为迷宫的初始化情形,迷宫如果除去其迷宫的外围框架就是一个7*7的矩阵,如果要生成一个完整的迷宫,那么就要遍历完图3.1所示的每一个可以行走的点,其中遍历的点也包含了入口和出口,如果每一个点都遍历完了就会生成一棵完整的遍历树,这棵遍历树包含了入口和出口所以这颗树所描述的迷宫是有解的(即:入口到出口时连通的。)图3.2就表示图1.1迷宫遍历所得到的遍历树,树包含了入口和出口所以此迷宫有解。 图3.2图3.3图3.3表示的是图3.2进一步的处理后得到的最终迷宫图,就是在图3.2的基础上把遍历树上的是墙壁的元素置为可行走的元素
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、连接到元素3和元素15,所以它可以遍历这两个元素,假设遍历的方向是随机的,如果第一次现在向右遍历那么元素3就被遍历并把它标志为flag(flag表示已经遍历过了不容许再次遍历),所以元素1和元素3都标志位flag说明在其它元素想遍历它们的时候是不能再次被遍历了。这就有可能会遍历成一棵完整的树。图3.1.2如图3.1.3所示图1.1迷宫在生成时前13步,据图我们可知在第13步的时候遍历到元素19,但是元素19周围的点都已经遍历过但同时还有其它元素还没有遍历到,所以要后退到上一个遍历过的元素判断是否有遍历的方向,所以链表到元素17,但是此元素也没有可遍历的方向所以要一直往上链表直到链表到某一个可以
4、重新遍历的点为之。 图3.1.3图3.1.4是往上链表的示意图直到链表到元素45发现此元素拥有可遍历的方向,所以又重新往下建立新的链表,即元素47 图3.1.4图3.1.5是最终遍历完后的遍历路径,此时只要沿着遍历的方向把相应的“墙”拆掉就可以生成一个无外框的迷宫并且只能生成奇数行和奇数列的迷宫。 图3.1.5图3.1.6是程序生成得33*33的迷宫 图3.1.64、编程思路5、源代码#include#include using std:cout;cin;endl;#define Row 33 /用于定义迷宫的行必须为奇数,否则不能遍历到所以的点#define Col 33 /用于定义迷宫的列
5、必须为奇数,否则不能遍历到所以的点#define flag 1 /点的标志位,如果找到符合条件的点就把它置为flag,只要某一个点置位为flag就不能再次被访问;int x_row=0; /迷宫的起始点位置的x坐标int y_col=0; /迷宫的起始点位置的y坐标int Left=0; /初始化向左的方向标志位Leftint Right=0; /初始化向右的方向标志位Rightint Up=0; /初始化向上的方向标志位Upint Dwon=0; /初始化向下的方向标志位Dwonint pointcount=(Row+1)*(Col+1)/4-1); /初始化要遍历的点数,(因为第一个点不要
6、遍历了,所以总点数要减去1)int get_count(); /定义可以获得某一个点可以行走的方向数的函数class mazepoint /定义一个类用于存放每一个遍历点的坐标public: int xtemp; /用于存放一个遍历点的x坐标 int ytemp; /用于存放一个遍历点的y坐标 mazepoint *next; /用于存放一个遍历点的下一个遍历点的地址 mazepoint *last; /用于存放一个遍历点的上一个遍历点的地址;mazepoint *p1;mazepoint *p2;mazepoint *head=NULL; /初始化头由于没有指向如何位置所以赋值为NULLma
7、zepoint *tail=NULL; /初始化尾由于没有指向如何位置所以赋值为NULLint mazemapRowCol= /初始化迷宫地图数组 1int main() p1=new mazepoint; /声明一片内存空间 p1-xtemp=0; /初始化类元素x坐标ytemp=0; /初始化类元素y坐标last=NULL; /初始类只有一个元素没有前一个元素,链接到别的元素所以它的的上一个遍历点位空NULL head=p1; /把链表的头地址赋值给p1 tail=p1; /刚刚开始没有其它元素所以把链表的尾地址也是p1 int mazenum=0; /用于统计遍历的次数 srand(ti
8、me(0); /用当前时间做随机种子数 while(pointcount) /如果没有遍历完所有的点就继续遍历,以确保每一次的随机数都不一样 int rdNo=rand(); /获得随机数 int Randtemp; /定义一个变量,用于存储处理后的随机数 int tempflag; /定义一个变量,用于存储某一个点可以行走的方向数 tempflag=get_count();/获得某一个点可以行走的方向数 if(tempflag!=0) /如果某一个点可以行走就处理随机数然后随机选择行走的方向 Randtemp=rdNo%tempflag; /根据返回的可以行走的方向提供行走方向数 else
9、Randtemp=NULL; /如果不能行走就赋值为NULL cout电脑随机数为: rdNo/输出电脑产生的随机数 Randtemp+=1; /加1是为了和定义的方向Left,Right,Up,Dwon相匹配随机数为: Randtempxtemp=x_row; /保存当前点的x坐标ytemp=y_col; /保存当前点的y坐标 p1=new mazepoint; /声明内存 p2-next=p1; /前一个遍历点链表到下一个点的地址last=p2; /后一个遍历点链表到上一个点的地址next=NULL; /新生产的点没有链表到下一个点所以设为NULL。(新产生的点是链表的最后一个点) if(
10、Randtemp=Left & mazemapx_rowy_col-2!=flag) /判断左边是否可以走如果可以走就不为;flagRandtemp=Left表示随机数等于Left /* / mazemapx_rowy_col;新遍历到的位置 * / 上一次确定的位置 * / mazemapx_rowy_col+1;新遍历到位置的相同方向的临近元素 * y_col-=2; /如果可以左走就要把对应的坐标也要改变;也就是行值减2 mazemapx_rowy_col=flag; /把遍历到的新的迷宫地图元素也要置flag mazemapx_rowy_col+1=flag;/把遍历到的新的迷宫地图元
11、素相同方向的临近元素也要置flag -pointcount; /遍历到新的一个点,那么遍历点的总数pointcount减1 coutI choice Left else if(Randtemp=Right & mazemapx_rowy_col+2!=flag)/判断右边是否可以走如果可以走就不为;flagRandtemp=Right表示随机数等于Right /* / mazemapx_rowy_col;新遍历到的位置 * / 上一次确定的位置 * / mazemapx_rowy_col-1; y_col+=2; /如果可以右走就要把对应的坐标也要改变;也就是行值加2 mazemapx_rowy_col-1=flag;I choice Right
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1