一、问题概述
小时候,我们都玩过走迷宫的游戏吧。看一下这个图例:
遇到这种问题时,我们第一反应都会先找到迷宫的入口点,然后对上下左右四个方向进行寻迹,
检测当前位置是否是通路,是否可以通过,直至找到出口位置,才是迷宫的正确轨迹。如若走到死胡
同里,则必须返回重新选择路径走。
我们来模拟一下迷宫问题,我们的迷宫是这样的:
哈哈~虽然有点low!但是可以帮助我们解决实际问题,就将就着看吧,这个更能清晰的说明问题哦。
那么这个迷宫从何而来呢?我将它放在文件中,以读取文件的方式,将其坐标保存在二维数组中喽。
二、解决方案
(1)找到入口点(entry),这个由我们自己给定坐标即可。
(2)使用试探法对迷宫寻迹,有上下左右四个方向,将走过的路径标记一下,将值赋值为其他
值。(这里我将它赋为2)
(3)如果走进死胡同里,则采用回溯的思想,将其pop即可。
(4)判断何时为迷宫出口,当它的横坐标为(行数-1)时,说明已找到出口。(当然,在这里你
也可以不用规定出口就在最下方,视迷宫的图例而定)
(5)若迷宫没有出口,则栈为空。
三、实现代码
//Maze.h
#include<iostream>
using namespace std;
#include<assert.h>
#include<stack>struct Pos
{int _row;int _col;
};void GetMaze(int *Maze,size_t N)
{FILE* fout = fopen("Maze.txt","r");assert(fout);for(size_t i = 0; i < N; ++i){for(size_t j = 0; j < N; ){int value = fgetc(fout);if(value == '1' || value == '0'){Maze[i*N+j] = value - '0';++j;}else if(value == EOF){cout<<"Maze error!"<<endl;return;}}}
}bool IsCheckPath(int *maze,size_t n,Pos path)
{if((path._row >= 0 && path._row < 10) && (path._col >= 0 && path._col < 10) && (maze[path._row*n+path._col] == 0)){return true;}return false;
}//栈求解迷宫路径
void GetMazePath(int *maze,size_t n,Pos entry,stack<Pos>& s)
{Pos cur = entry;Pos next = cur;maze[cur._row*n+cur._col] = 2;s.push(entry);while(!s.empty()){if(s.top()._row == n-1){return;}//探测上下左右//上next = s.top();next._row-=1;if(IsCheckPath(maze,n,next)){s.push(next);maze[next._row*n+next._col] = 2;continue;}//右next = s.top();next._col+=1;if(IsCheckPath(maze,n,next)){s.push(next);maze[next._row*n+next._col] = 2;continue;}//下next = s.top();next._row+=1;if(IsCheckPath(maze,n,next)){s.push(next);maze[next._row*n+next._col] = 2;continue;}//左next = s.top();next._col-=1;if(IsCheckPath(maze,n,next)){s.push(next);maze[next._row*n+next._col] = 2;continue;}//没有通路Pos tmp = s.top();maze[tmp._row*n+tmp._col] = 3;s.pop();}
}//递归求解迷宫路径
void GetMazePath(int *maze,size_t n,Pos entry,stack<Pos>& s)
{Pos next = entry;maze[next._row*n+next._col] = 2;s.push(entry);if(next._row == n-1){return;}//探测上下左右//上next = entry;next._row-=1;if(IsCheckPath(maze,n,next)){GetMazePath(maze,n,next,s);}//右next = entry;next._col+=1;if(IsCheckPath(maze,n,next)){GetMazePath(maze,n,next,s);}//下next = entry;next._row+=1;if(IsCheckPath(maze,n,next)){GetMazePath(maze,n,next,s);}//左next = entry;next._col-=1;if(IsCheckPath(maze,n,next)){GetMazePath(maze,n,next,s);}
}void PrintMaze(int *maze,size_t n)
{cout<<"迷宫显示:>"<<endl;for(size_t i = 0; i < n; ++i){for(size_t j = 0; j < n; ++j){cout<<maze[i*n+j]<<" ";}cout<<endl;}
}
//Maze.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"Maze.h"//用栈和递归实现迷宫问题
const size_t N = 10;void FunTest()
{int Maze[N][N];Pos entry = {2,0};stack<Pos> ss;GetMaze((int*)Maze,N);GetMazePath((int*)Maze,N,entry,ss);cout<<"迷宫是否有出口?"<<!ss.empty()<<endl;PrintMaze((int*)Maze,N);
}int main()
{FunTest();return 0;
}
用栈和递归实现普通的迷宫问题还是可以的,但是还有一种这样的迷宫:
当有多条路径的时候,就会涉及到路径长短的问题,到底走哪条路径会是最优。下篇博客给大家介绍哦。
希望看过此篇博客的编程爱好者提出见解哈。