给定一张迷宫地图和一个迷宫入口,然后进入迷宫探索找到一个出口。如下图所示:
该图是一个矩形区域,有一个入口和出口。迷宫内部包含不能穿越的墙壁或者障碍物。这些障碍物沿着行和列放置,与迷宫的边界平行。迷宫的入口在左上角,出口在右下角。
(1)一是迷宫中各处的位置坐标,
(2)二是迷宫各位置处的状态信息,即该处是墙还是路
所以,该迷宫地图可由一个二维数组来表示。数组的横纵坐标表示迷宫各处的位置坐标,数组元素表示各位置处的状态信息。
2.在这里,假定:
(1)迷宫地图是m*n的,即二维数组是m行n列的。
(2)在迷宫中用1表示墙,用0表示路。当然,为了便于标识,我们后面还会用其他数字代表更多含义。
因此,迷宫的地图一个刻画如下:
现在我们要找一条从入口到出口的路径。路径是一个由位置组成的序列,每一个位置都没有障碍,并且除入口外,路径上的每一个位置都是前一个位置在东西南北方向上相邻的一个位置。
不过,考虑到边界问题不太好处理。我们做这样的工作,在地图外围加一层围墙,给它全部填上1。这样,在处理各个坐标时,都没有差别了。这样一来便大大简化了我们的工作。
下面我们要编写程序求解这个问题。
这次还是采用一个简单的模块化来设计这个程序。那么主要有下面几个模块:
下面我们分别完成这些功能。
这个模块就很简单了,输出一些信息提醒使用者就行,主要是为了增加程序的友好性而设置的。大家根据自己的需要自行发挥。例如我的就很随便了:
void welcome()
{
cout << "welcome to RAT IN MAZE" << endl;
system("pause");
system("cls");
}
这个主要是设置一些全局变量的取值和完成内存的分配,地图的存储还是从堆上分配内存比较好。因为一般来说,考虑到地图可能会很大,这样需要的存储空间就很多了。在这里一并把相关的全局变量给讲解了吧。
typedef struct
{
int row;
int col;
}POSITION;
const POSITION maze_size = { 20 , 60 };
int ** const maze = new int*[maze_size.row + 2];
stack<POSITION> path;
POSITION offset[4];//direction
void init()
{
//偏移
offset[0].row = 0; offset[0].col = 1; //right
offset[1].row = 1; offset[1].col = 0; //down
offset[2].row = 0; offset[2].col = -1; //left
offset[3].row = -1; offset[3].col = 0; //up
//maze = new int*[maze_size.row + 2];
for (int i = 0; i < maze_size.row + 2; i++)
{
maze[i] = new int[maze_size.col + 2];
}
}
这个代码就是设置偏移的数值,以及动态分配地图数组了。
生成地图还是根据地图尺寸,然后随机设置障碍。不过要注意障碍出现的概率设置得小一点,不然地图一般无解。可以用rand()随机数来做。这一步也要把围墙设置好。
//地图范围1 - maze_size 有围墙
void randomMaze()
{
int i, j, rate;
for (i = 0; i < maze_size.row + 2; i++)
{
for (j = 0; j < maze_size.col + 2; j++)
{
//设置围墙
if ((i == 0) || (i == maze_size.row + 1) || (j == 0) || (j == maze_size.col + 1))
{
maze[i][j] = 1;
}
else
{
rate = rand() % 10+1;
if (rate <= 3)
{
maze[i][j] = 1;//随机生成障碍
}
else
{
maze[i][j] = 0;
}
}
}
}
//最后保证起点和终点能走
maze[1][1] = maze[maze_size.row][maze_size.col] = 0;
}
这个是整个程序设计的核心功能,没有之一。在写代码之前,我们需要弄明白,到底怎么找路呢?
例如,下面的地图:
好了,说了这么多,相信大家已经了解得差不多,并且跃跃欲试了。
bool findPath()
{
POSITION here; //当前位置
here.row = here.col = 1;
maze[1][1] = 3; //放置障碍,防止回来
int option = 0; //next step
const int lastOption = 3;
//find a path
while ( here.row != maze_size.row || here.col != maze_size.col)
{
//not reach the end
int r, c;
while (option <= lastOption)
{
r = here.row + offset[option].row;
c = here.col + offset[option].col;
if (maze[r][c] == 0)
{
break;
}
option++;//next choice
}
//相邻的位置能走?
if (option <= lastOption)
{
path.push(here);
here.row = r;
here.col = c;
maze[r][c] = 3; //走过了
option = 0;
}
else
{
if (path.empty())
{
return false;
}
//go back
maze[here.row][here.col] = 3; //此路不可通
here = path.top();
path.pop();
option = 0;
}
}
maze[maze_size.row][maze_size.col] = 2;
return true;
}
相关代码如上面所示,结合前面的讲解,相信大家也能看懂。
这个功能就比较简单了,主要是根据maze的信息,生成相应的地图显示出来给大家直观的看到。对于maze里面存的数值,我们也可以作一个小小的规定:
然后打印的时候,遍历maze数组,遇到:
最后在打印最终的地图和路径之前,如果找到一条路径。我们还要根据path中的路径,在maze里面设置好相应的值,才做最终的输出:
void setPathOnMaze()
{
POSITION pos;
while (!path.empty())
{
pos = path.top();
path.pop();
maze[pos.row][pos.col] = 2;//路径
}
}
然后,可以开始输出我们的地图了。
具体代码:
void outputMaze()
{
int i, j;
for (i = 0; i < maze_size.row + 2; i++)
{
for (j = 0; j < maze_size.col + 2; j++)
{
if (maze[i][j] == 1)
{
cout << "*";
}
else if ((maze[i][j] == 0) || (maze[i][j] == 3))
{
cout << " ";
}
else
{
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut,FOREGROUND_GREEN | FOREGROUND_INTENSITY);
cout << "#";
SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
}
cout << endl;
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。