Day8:寻路算法---深度寻路

本文详细介绍了深度寻路算法的基本思路,包括规定试探方向顺序、实时记录路径状态、栈结构的回退机制,以及代码中数据结构(栈)的使用和路径搜索的具体实现。通过实例展示了如何利用栈实现从起点到终点的路径探索,适用于图形或网格状环境的路径查找。

一、基础概念:

寻路算法 --- 深度寻路算法_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());
}

又遇到上次的bug了--->直接放上次写博客链接了。【BUG----优先级】7.9 被?:问号冒号表达式的优先级坑了https://blog.youkuaiyun.com/zjjaibc/article/details/125694367?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22125694367%22%2C%22source%22%3A%22zjjaibc%22%7D&ctrtid=1RMiZ

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;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Ocean__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值