废话不多说,直接开搞
1.看图
先看图
让起点上的小人从起点一直到终点,看图看不了多少直接看方法
2.方法
1.走的方法
1.1按照上,左,下,右逆时针方向行走
1.2总不能回头走吧,所以将走过的路径标为已走过(,下次就不会走了
2.遇到什么不能走
2.1有障碍(图中有颜色部分)
2.2死胡同(图中箭头所指),在这里不管是上方已经被标记已走过,还是左,下,右都是障碍。所以我们需要利用栈后入先出的原理,将走过的路径入栈,遇到这种情况就出栈直到岔路口。
~详细过程在代码注释中,所以下面请看代码
3.代码
首先先准备一个栈(MyStack.h):
这里我采用的是C++的写法
#include<iostream>
#include<stdlib.h>
using namespace std;
template<class T>
class Stack
{
private:
T * pBuff; //内存段首地址
int len; //栈内元素
int maxLen; //当前栈内存大小
public:
Stack()
{
pBuff = NULL;
len = maxLen = NULL;
}
~Stack()
{
if (pBuff)
delete[] pBuff;
pBuff = NULL;
len = maxLen = NULL;
}
//出栈
void Pop()
{
len--;
}
//入栈
void Push(const T& Data);
//是否为空
bool IsEmpty()
{
return (pBuff == NULL);
}
//得到栈顶元素
T getBuff()
{
return pBuff[len - 1];
}
};
//入栈
template<class T>
void Stack<T>::Push(const T& Data)
{
if (len >= maxLen)
{
//1.首先要开辟一个内存
//1.1计算内存大小
maxLen = maxLen + (((maxLen >> 1) > 1) ? (maxLen>>1) : 1);
T * pTemp = new T[maxLen];//这里新的内存段要比原来内存要大
//2.将pBuff拷贝到pTemp中去
if (pBuff)
{
memcpy(pTemp, pBuff, sizeof(T)* len);
delete[] pBuff;
}
//3.pBuff指向pTemp
//这个时候的pTemp比原来的pBuffer内存要大也能更好的传递数据
pBuff = pTemp;
}
//4.插入数据
pBuff[len++] = Data;
}
下面来看main函数
#include"MyStack.h"
#define ROW 10
#define COL 10
struct MyPoint
{
int x;
int y;
};
enum direct{Up,Left,Down,Right};
struct TestMap
{
int dir; //方向(枚举)
bool IsFind; //判断走没走过
};
int main()
{
//1.寻路前的准备
//1.1首先创建一个地图
int Map[ROW][COL] = {//这里的1表示障碍,0表示可以走的路
1,1,1,1,1,1,1,1,1,1,
1,0,1,1,1,1,1,1,1,1,
1,0,1,1,1,1,1,1,1,1,
1,0,1,1,1,1,1,1,1,1,
1,0,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,1,1,1,
1,0,1,1,1,1,0,1,1,1,
1,0,1,1,1,1,0,1,1,1,
1,0,1,1,1,1,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,
};
//1.2初始化起点和终点
MyPoint begPos = { 1,1 }; //起点
MyPoint endPos = { 8,8 }; //终点
//1.3定义当前点和试探点
MyPoint currectPos = begPos; //当前点从起点开始
MyPoint searchPos;
//1.4准备一个测试地图(用于标记已走过)
TestMap testMap[ROW][COL] = { 0 };
testMap[currectPos.x][currectPos.y].IsFind = true; //标记起始地点已经走过
//1.5开栈
Stack<MyPoint> stack;
stack.Push(begPos); //起点入栈
bool IsFind;
//2.开始寻路
while (1)
{
searchPos = currectPos;
//根据当前点来判断方向
switch(testMap[currectPos.x][currectPos.y].dir)
{
case Up:
searchPos.y--; //向上y做减减运算
testMap[currectPos.x][currectPos.y].dir++;//试探点换方向
//判断能不能走
if (Map[searchPos.x][searchPos.y] == 0//没有障碍
&& testMap[searchPos.x][searchPos.y].IsFind == false)//没走过
{
//能走
currectPos = searchPos; //当前点等于试探点
//坐标入栈
stack.Push(searchPos);
//标记已走过
testMap[searchPos.x][searchPos.y].IsFind = true ;
}
break;
case Left:
searchPos.x--; //向上y做减减运算
testMap[currectPos.x][currectPos.y].dir++;//试探点换方向
//判断能不能走
if (Map[searchPos.x][searchPos.y] != 1//没有障碍
&& testMap[searchPos.x][searchPos.y].IsFind == false)//没走过
{
//走
currectPos = searchPos; //当前点等于试探点
//坐标入栈
stack.Push(searchPos);
//标记已走过
testMap[searchPos.x][searchPos.y].IsFind = true;
}
break;
case Down:
searchPos.y++; //向上y做减减运算
testMap[currectPos.x][currectPos.y].dir++;//试探点换方向
//判断能不能走
if (Map[searchPos.x][searchPos.y] != 1//没有障碍
&& testMap[searchPos.x][searchPos.y].IsFind == false)//没走过
{
//能走
currectPos = searchPos; //当前点等于试探点
//坐标入栈
stack.Push(searchPos);
//标记已走过
testMap[searchPos.x][searchPos.y].IsFind = true;
}
break;
case Right:
searchPos.x++; //向上y做减减运算
testMap[currectPos.x][currectPos.y].dir++;//试探点换方向
//判断能不能走
if (Map[searchPos.x][searchPos.y] != 1//没有障碍
&& testMap[searchPos.x][searchPos.y].IsFind == false)//没走过
{
//能走
currectPos = searchPos; //当前点等于试探点
//坐标入栈
stack.Push(searchPos);
//标记已走过
testMap[searchPos.x][searchPos.y].IsFind = true;
}
else//走到死胡同了
{
//回退
//删除栈顶元素
stack.Pop();
//当前的点被栈顶元素赋值
currectPos = stack.getBuff();
}
break;
default:
break;
}
//如果当前点等同于终点时退出循环
if (currectPos.x == endPos.x && currectPos.y == endPos.y)
{
IsFind = true;
break;
}
//如果整个地图中都没有终点的,那就会一直回退,知道栈里面的元素为空
if (stack.IsEmpty())
{
break;
}
}
if (IsFind)
{
printf("找到终点了");
}
else
{
printf("没找到");
}
return 0;
}
4.总结
我个人感觉寻路算法一定要好好研究,对于我这样的初学者来说,这其中包含的思想和逻辑都十分重要,学算法学的就是它的逻辑和思维。下面我还会学习介绍广度寻路和A星寻路。