一、基础概念:
寻路算法 --- 深度寻路算法_
https://blog.youkuaiyun.com/weixin_60569662/article/details/123651939
思路:
1. 规定试探方向顺序
顺时针(上 右 下 左) 逆时针(上 左 下 右)
2. 实时记录每个点 当前试探方向
实时记录每个点 是否走过
3. 回退
每走一步,栈结构存储当前位置
需要回退的时候:
删除当前栈顶元素
跳到当前栈顶元素处
4. 遇到终点
循环结束 栈结构存储起点到终点的路径
整个地图都找不到终点 栈为空
二、代码实现
1.数据结构----栈的准备
#pragma once
#include<iostream>
#include<stdlib.h>
#include<cstring>
using namespace std;
template <class T>
class MyStack
{
public:
MyStack()
{
pBuffer = nullptr;
len = maxLen = 0;
}
~MyStack()
{
if (pBuffer)delete[]pBuffer;
pBuffer = nullptr; len = maxLen = 0;
}
void pop() { if(len>0)len--; }
T GetTop() { return pBuffer[len - 1]; }
bool isEmpty() { return (len == 0); }
void push(const T& data);
private:
T* pBuffer;
int len;
int maxLen;
};
template<class T>
inline void MyStack<T>::push(const T& data)
{
if (len >= maxLen)//此时需要另外开内存
{
maxLen +=(((maxLen >> 1>1)) ? maxLen >> 1 : 1);//若整除之后为0,至少得增加一个
T* pNew = new T[maxLen];
if (pBuffer)//之前存在的话,才需要进行memcpy
{
memcpy(pNew, pBuffer, len * sizeof(T));
delete []pBuffer;
}
pBuffer = pNew;
}
pBuffer[len++] = data;
//_ASSERTE(_CrtCheckMemory());
}
2.准备工作:
辅助地图(是否走过、当前点的探索方向)、正式地图、描述坐标的类
注:最好用0来初始化->0来代表第一个方向up&&用0来是否走过(一键初始化)
#include"MyStack.h"
#include<graphics.h>
#include<Windows.h>
#define ROWS 10
#define COLS 10
enum dir
{
UP, LEFT, DOWN, RIGHT
};//默认值为0,1,2,3
//辅助地图
struct pathNode
{
int dir;//当前的探索方向
bool isArrive;//是否走过了 0表示没走过
};
//人物or探索位置的坐标
struct pos
{
int row;
int col;
bool operator==(const struct pos b)
{
return (row == b.row) && (col == b.col);
}
};
int MAP[ROWS][COLS] =
{{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 1, 0, 0, 0, 1, 0, 0, 1 },
{ 1, 0, 1, 0, 1, 1, 1, 1, 0, 1 },
{ 1, 0, 1, 0, 0, 0, 0, 1, 0, 1 },
{ 1, 0, 1, 0, 1, 1, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 1, 1, 0, 1, 0, 1 },
{ 1, 0, 1, 1, 1, 0, 0, 1, 0, 1 },
{ 1, 0, 1, 0, 0, 0, 1, 1, 0, 1 },
{ 1, 0, 1, 0, 1, 1, 1, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }};//0表示road
struct pos beg_xy = { 1,1 };//起点
struct pos pos_xy = { 8,7 };//终点
struct pathNode pathmap[ROWS][COLS] = { 0 };//一键重置新地图(0->up&&没走过)
IMAGE people, road, wall, pos,beg,ball;
#define WIDTH 80 //单个贴图的大小
void drawmap(int MAP[ROWS][COLS],struct pos pep, struct pos beg, struct pos end);
void init();
void init()
{
//1.创建窗口
initgraph(COLS * WIDTH, ROWS * WIDTH, SHOWCONSOLE);
//2.加载绑定图片(注意字符集兼容问题)
loadimage(&people,"res/people.bmp", WIDTH, WIDTH, true);
loadimage(&wall, "res/wall.bmp", WIDTH, WIDTH, true);
loadimage(&road, "res/road.bmp", WIDTH, WIDTH, true);
loadimage(&pos, "res/pos.bmp", WIDTH, WIDTH, true);
loadimage(&beg, "res/beg.bmp", WIDTH, WIDTH, true);
loadimage(&ball, "res/ball.bmp", WIDTH/2, WIDTH/2, true);
}
void drawmap(int MAP[ROWS][COLS],struct pos pep,struct pos begin,struct pos end)
{
for (int i = 0; i < COLS; i++)
{
for (int j = 0; j < ROWS; j++)
{
if (pep.row == i && pep.col == j)
putimage(j * WIDTH, i * WIDTH, &people);
else if (begin.row == i && begin.col == j)
putimage(j * WIDTH, i * WIDTH, &beg);
else if (end.row == i && end.col == j)
putimage(j * WIDTH, i * WIDTH, &pos);
else if (MAP[i][j] == 1)
putimage(j * WIDTH, i * WIDTH, &wall);
else if (MAP[i][j] == 0)
putimage(j * WIDTH, i * WIDTH, &road);
}
}
}
3.核心逻辑(栈的回退->探索到最后一个方向right开始判断)
1.已知当前点的坐标,找试探点-> 在辅助地图中记录了当前点的当前试探方向
2.判断试探点是否能走, 如果能走,走的时候标记点已经走过了,要入栈 如果不能走:
2.1.(前面三个方向中某一个能走)试探方向改变
2.2.(第四个方向还是不能走) 回退,删除栈顶元素,跳到当前栈顶元素处即可
3.判断是否结束循环
3.1找到终点了
3.2没有找到终点,但是栈空了-> 整个地图都找遍了
int main()
{
init();
struct pos people_xy=beg_xy;
struct pos search_xy;
MyStack<struct pos>trait;//存放路径
trait.push(beg_xy);//起点入栈
pathmap[beg_xy.row][beg_xy.col].isArrive = true;//起点标记走过
bool isFind = false;
while (!isFind)
{
search_xy = people_xy;//每次循环之前,都要重置searchNode的位置
//cout << pathmap[people_xy.row][people_xy.col].dir << endl;
switch (pathmap[people_xy.row][people_xy.col].dir)
{
case UP:
pathmap[people_xy.row][people_xy.col].dir++;//先改变当前点的dir!!!便于下次寻路
search_xy.row--;
if (MAP[search_xy.row][search_xy.col] == 0 &&//是路road 0
pathmap[search_xy.row][search_xy.col].isArrive == 0)//且没走过
{
people_xy = search_xy;//走一步
pathmap[search_xy.row][search_xy.col].isArrive = true;//标记走过!!
trait.push(people_xy);//入栈
}
break;
case LEFT:
pathmap[people_xy.row][people_xy.col].dir++;//先改变当前点的dir!!!便于下次寻路
search_xy.col--;
if (MAP[search_xy.row][search_xy.col] == 0 &&//是路road 0
pathmap[search_xy.row][search_xy.col].isArrive == 0)//且没走过
{
people_xy = search_xy;//走一步
pathmap[search_xy.row][search_xy.col].isArrive = true;
trait.push(people_xy);//入栈
}
break;
case DOWN:
pathmap[people_xy.row][people_xy.col].dir++;//先改变当前点的dir!!!便于下次寻路
search_xy.row++;
if (MAP[search_xy.row][search_xy.col] == 0 &&//是路road 0
pathmap[search_xy.row][search_xy.col].isArrive == 0)//且没走过
{
people_xy = search_xy;//走一步
pathmap[search_xy.row][search_xy.col].isArrive = true;
trait.push(people_xy);//入栈
}
break;
case RIGHT:
//pathmap[people_xy.row][people_xy.col].dir++;//先改变当前点的dir!!!便于下次寻路
search_xy.col++;
if (MAP[search_xy.row][search_xy.col] == 0 &&//是路road 0
pathmap[search_xy.row][search_xy.col].isArrive == 0)//且没走过
{
people_xy = search_xy;//走一步
pathmap[search_xy.row][search_xy.col].isArrive = true;
trait.push(people_xy);//入栈
break;
}//如果到这了,还没有break,那么说明此点不能走->需要回退
trait.pop();
people_xy = trait.GetTop();//别忘记改人物位置
}
Sleep(20);
drawmap(MAP, people_xy, beg_xy, pos_xy);
if (pos_xy == people_xy)isFind = true;
if (trait.isEmpty())break;
}//在栈上开辟的空间记得释放
if (isFind)
{
cout << "找到了!" << endl;
while (!trait.isEmpty())
{
cout << '[' << trait.GetTop().row << ',' << trait.GetTop().col << ']';
putimage(trait.GetTop().col * WIDTH + WIDTH / 4, trait.GetTop().row * WIDTH + WIDTH / 4, &ball);
trait.pop();
}
}
while (1);
return 0;
}
本文详细介绍了深度寻路算法的基本思路,包括规定试探方向顺序、实时记录路径状态、栈结构的回退机制,以及代码中数据结构(栈)的使用和路径搜索的具体实现。通过实例展示了如何利用栈实现从起点到终点的路径探索,适用于图形或网格状环境的路径查找。
1676

被折叠的 条评论
为什么被折叠?



