假设这是一幅迷宫地图,‘0’表示通路,‘1’表示墙不能通过,‘entry’表示迷宫的入口。那么怎么从中找到出口呢?!这就是这篇文章要解决的问题。
一、思路:
我们可以利用回溯法的思想,也就是所谓的试探法:每走一步,我们都有上、下、左、右四个方向要去试探,如果该方向是‘0’,那么就继续向下走,并继续试探;否则退回一步,走另外一个方向...
此外,我们还要借助栈来存放走过的路径:向前走的时候每走一步将该位置push入栈,退回的时候pop退栈。
栈的模拟实现:点击打开链接
二、实现:
1.首先,我们需要从文件中读取数据(迷宫地图)
void InitMaze(int *a,int rows,int cols) //读取文件
{
FILE* pf =fopen("Maze.txt","r");
assert(pf);
for (int i=0; i<rows; i++)
{
for (int j=0; j<cols;)
{
char value = fgetc(pf);
if (value == '0' || value == '1')
{
a[i*N+j] = value-'0';
j++;
}
}
}
}
2.接下来就是找通路的问题了:
在这一部分主要的有三部分:a.表示位置的结构体b.判断此位置是否能通过的函数
c.最主要的一个函数------找通路
struct Pos
{
int _row;
int _col;
Pos(int rows = 0, int cols = 0)
:_row(rows)
,_col(cols)
{}
};
bool CheckAccess(int* maze,Pos pos) //判断当前位置是否是通路
{
if ((pos._row >= 0 ) && (pos._row < N)
&& (pos._col >= 0) && (pos._col < N)
&& (maze[pos._row*N+pos._col] == 0))
return true; //是通路
return false; //不是通路
}
void make_push(int* maze,Stack<Pos>& path,Pos pos) //将当前位置压入栈
{
path.Push(pos);
maze[pos._row*N+pos._col] = 2; //将走过的路径标记为2
}
bool chech_exit(int* maze, int rows,int cols,Pos pos) //判断是否走到出口
{
if ((pos._row == rows-1) || (pos._col == cols-1) || (pos._row == 0))
{
return true;
}
return false;
}
bool GetPath(int* maze, int rows,int cols,Stack<Pos>& path,Pos entry)
{
make_push(maze,path,entry); //入口标记为2
while(!path.Empty())
{
Pos cur = path.Top(); //每次读取栈顶的元素,即当前位置
Pos next = cur;
//上
next._row -= 1;
if (CheckAccess(maze,next))
{
make_push(maze,path,next);//将走过的路压入栈
continue;
}
next._row += 1;
//右
next._col += 1;
if (CheckAccess(maze,next))
{
make_push(maze,path,next);
continue;
}
next._col -= 1;
//下
next._row += 1;
if (CheckAccess(maze,next))
{
make_push(maze,path,next);
continue;
}
next._row -= 1;
//左
next._col -= 1;
if (CheckAccess(maze,next))
{
make_push(maze,path,next);
continue;
}
next._col += 1;
if (chech_exit(maze,rows,cols,next)) //判断出口
{
return true;
}
maze[cur._row*cols+cur._col]=3; //退栈时将回路标记为3,只是为了体现回溯的思想
path.Pop();
}
return false;
}
3.打印迷宫
void Ptintmaze(int *a,int rows,int cols) //打印迷宫
{
for (int i=0; i<rows; i++)
{
for (int j=0; j<cols;j++)
{
cout<<a[i*N+j]<<' ';
}
cout<<endl;
}
cout<<endl;
}
三、总体代码实现
#pragma once
#include "Stack.h"<span style="white-space:pre"> </span>//这里是自己实现的栈
const int N=10;
void InitMaze(int *a,int rows,int cols) //读取文件
{
FILE* pf =fopen("Maze.txt","r");
assert(pf);
for (int i=0; i<rows; i++)
{
for (int j=0; j<cols;)
{
char value = fgetc(pf);
if (value == '0' || value == '1')
{
a[i*N+j] = value-'0';
j++;
}
}
}
}
void Ptintmaze(int *a,int rows,int cols) //打印迷宫
{
for (int i=0; i<rows; i++)
{
for (int j=0; j<cols;j++)
{
cout<<a[i*N+j]<<' ';
}
cout<<endl;
}
cout<<endl;
}
struct Pos
{
int _row;
int _col;
Pos(int rows = 0, int cols = 0)
:_row(rows)
,_col(cols)
{}
};
bool CheckAccess(int* maze,Pos pos) //判断当前位置是否是通路
{
if ((pos._row >= 0 ) && (pos._row < N)
&& (pos._col >= 0) && (pos._col < N)
&& (maze[pos._row*N+pos._col] == 0))
return true; //是通路
return false; //不是通路
}
void make_push(int* maze,Stack<Pos>& path,Pos pos) //将当前位置压入栈
{
path.Push(pos);
maze[pos._row*N+pos._col] = 2; //将走过的路径标记为2
}
bool chech_exit(int* maze, int rows,int cols,Pos pos) //判断是否走到出口
{
if ((pos._row == rows-1) || (pos._col == cols-1) || (pos._row == 0))
{
return true;
}
return false;
}
bool GetPath(int* maze, int rows,int cols,Stack<Pos>& path,Pos entry)
{
make_push(maze,path,entry); //入口标记为2
while(!path.Empty())
{
Pos cur = path.Top(); //每次读取栈顶的元素,即当前位置
Pos next = cur;
//上
next._row -= 1;
if (CheckAccess(maze,next))
{
make_push(maze,path,next);//将走过的路压入栈
continue;
}
next._row += 1;
//右
next._col += 1;
if (CheckAccess(maze,next))
{
make_push(maze,path,next);
continue;
}
next._col -= 1;
//下
next._row += 1;
if (CheckAccess(maze,next))
{
make_push(maze,path,next);
continue;
}
next._row -= 1;
//左
next._col -= 1;
if (CheckAccess(maze,next))
{
make_push(maze,path,next);
continue;
}
next._col += 1;
if (chech_exit(maze,rows,cols,next)) //判断出口
{
return true;
}
maze[cur._row*cols+cur._col]=3; //退栈时将回路标记为3
path.Pop();
}
return false;
}
void test_mase()
{
int maze[N][N];
InitMaze((int*)maze,N,N);
Ptintmaze((int*)maze,N,N);
Stack<Pos> path;
cout<<"是否有通路?"<<GetPath((int*)maze,N,N,path,Pos(3,0))<<endl;
Ptintmaze((int*)maze,N,N);
}
运行结果: