您的位置:首页 > 其它

以栈解决迷宫问题

2016-05-19 17:16 351 查看
怎么找到一个迷宫的出口呢。首先要知道迷宫长啥样,之后知道出入口,再之后就是找通路的过程了。

显然主要的部分是如何找通路。我们就举一个例子:





在这个迷宫中0就是墙,1就是路。那么我们可以用一个二维数组来表示这个迷宫。之后我们需要一种结构来实现我们表示位置的移动。
struct Pos
{
size_t line;
size_t row;
};
这个结构体通过记录行和列来表示现在处在迷宫的哪个位置。

现在就可以开始进行找通路的过程了。我们很容易想到通过试探当前位置的周围四个或三个位置来找到下一个应该去的位置,直到走到出口就算任务完成了。但是我们在试探的过程中,走到了下个位置,一定要把之前的位置做一个标记,否则我们的程序会一直在两个位置之间走来走去。我们这里通过把之前的位置置为2来防止它走来走去。

if (pos.row>0 && maze[pos.line * 10 + pos.row - 1] == 1)//左
{
p.push(pos.line * 10 + pos.row);
pos.row--;
maze[(pos.line * 10 + pos.row)] = 2;
}
else if (pos.row < 9 && maze[pos.line * 10 + pos.row + 1] == 1)//右
{
p.push(pos.line * 10 + pos.row);
pos.row++;
maze[(pos.line * 10 + pos.row)] = 2;
}
else if (pos.line > 0 && maze[(pos.line - 1) * 10 + pos.row] == 1)//上
{
p.push(pos.line * 10 + pos.row);
pos.line--;
maze[(pos.line * 10 + pos.row)] = 2;
}
else if (pos.line < 9 && maze[(pos.line + 1) * 10 + pos.row] == 1)//下
{
p.push(pos.line * 10 + pos.row);
pos.line++;
maze[(pos.line * 10 + pos.row)] = 2;
}
这段代码就是对上下左右四个方向进行试探的过程,其中我们用一个栈记录下了我们走过的位置,因为迷宫里面有岔路,所以我们走错时需要进行回溯。而选用栈是因为栈的后进先出的特性。说到走进岔路进行回溯,当我们发现上面四种试探完成却没有通路时,就是我们已经走到了死胡同的最深处,需要进行回溯了,那末回溯的过程就是进行拿取栈顶元素,之后出栈的过程。
maze[(pos.line * 10 + pos.row)] = 3;
pos.line = p.top() / 10;
pos.row = p.top() - pos.line*10;
p.pop();
上面的代码就是进行回溯的过程,再加一个是否到达终点的判断就完成了主要部分。

if (pos.line * 10 + pos.row == 91)
{
PrintMaze(maze);
return 1;
}


上面就是找路径的过程,也就是我们代码的主要逻辑部分。剩下的就是一些注意事项。

读迷宫图我是通过文件指针,fopen,fgets,fclose来实现的。之后在创建了一个二维数组之后我们给函数传参的时候需要把它转换成一个一级指针来传递。我们操作就把它当作一个一维数组来处理。因为在内存中一维数组和二维数组是一样的,只不过表示方式不一样而已,我们这个迷宫通过二维数组表示比较直观,但是用一维数组一样可以处理。

下面是完整的代码和运行的结果。

结果:



可以看到上面的是最初的迷宫,经过我们走迷宫的过程,将走过的岔路标记为了3,正确的通路标记为了2。

完整代码:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
#include<assert.h>
#include<stack>
using namespace std;

struct Pos { size_t line; size_t row; };

void InitMaze(int *maze)
{
FILE *p = fopen("maze.txt", "r");
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10;)
{
int tmp =(int)(fgetc(p))-'0';
if (tmp == 0)
maze[i*10+j] = 0;

if (tmp == 1)
maze[i*10+j] = 1;

if (tmp == 1 || tmp == 0)
j++;
}
}

fclose(p);
}

void PrintMaze(int *maze)
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
cout << maze[i * 10 + j] << " ";
}
cout << endl;
}
cout << endl;
}

int GoMaze(int *maze,Pos start)
{
assert(maze);
stack<int> p;

Pos pos;
pos.line = start.line;
pos.row = start.row;

while (1)
{
maze[(pos.line * 10 + pos.row)] = 2;

if (pos.row>0 && maze[pos.line * 10 + pos.row - 1] == 1)//左
{
p.push(pos.line * 10 + pos.row);
pos.row--;
maze[(pos.line * 10 + pos.row)] = 2;
}
else if (pos.row < 9 && maze[pos.line * 10 + pos.row + 1] == 1)//右
{
p.push(pos.line * 10 + pos.row);
pos.row++;
maze[(pos.line * 10 + pos.row)] = 2;
}
else if (pos.line > 0 && maze[(pos.line - 1) * 10 + pos.row] == 1)//上
{
p.push(pos.line * 10 + pos.row);
pos.line--;
maze[(pos.line * 10 + pos.row)] = 2;
}
else if (pos.line < 9 && maze[(pos.line + 1) * 10 + pos.row] == 1)//下
{
p.push(pos.line * 10 + pos.row);
pos.line++;
maze[(pos.line * 10 + pos.row)] = 2;
}
else
{
maze[(pos.line * 10 + pos.row)] = 3;
pos.line = p.top() / 10;
pos.row = p.top() - pos.line*10;
p.pop();
}

if (pos.line * 10 + pos.row == 91)
{
PrintMaze(maze);
return 1;
}
}
}

void Mazetest()
{
int maze[10][10];
Pos p;
p.line = 2;
p.row = 0;
InitMaze((int *)maze);
PrintMaze((int *)maze);
GoMaze((int *)maze,p);
}

int main()
{
Mazetest();
return 0;
}


本文出自 “刘子蛋好好学习” 博客,请务必保留此出处http://lzd1995.blog.51cto.com/10973198/1775112
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: