C++ 深度寻路简单实现

#include "stdafx.h"
#include <vector>
using namespace std;

//深度优先搜索(深度寻路)

//规则:沿着一个固定的方向来进行行走,到了岔路口又一次重新选择方向,如果碰上了死胡同退回到上一个岔路口重新选择方向
//		走过的路不会重复走,一次走一个岔路口

//注意:深度如果因为方向设定顺序不一致,可能导致找到的路径不一样
//深度最简单


//1、需要一张地图 (二维数组来表示地图)
//在二维数组中用一个固定的数值表示可通行(一般为0),其它的非0数值都理解不可通行
#define MAP_ROW 10
#define MAP_COL 10


//2、准备方向 帮助进行辅助寻路
enum Path_Dir {p_up,p_left,p_down,p_right};

//3、准备一个结构,用来保存每一个路径点的行列值
struct MyPoint
{
	int row, col;
};

//4、准备一个数据结构来保存寻路最终所找到的所有岔路口的坐标(准备一个栈来做为数据结构)

//5、为地图准备一个辅助的寻路地图(这个辅助地图不仅仅是一个变量能解决的,需要一个结构)
struct PathNode
{
	int val;//保存资源地图的岔路口信息
	Path_Dir dir;//为当前岔路口准备一个最初的寻路方向
	bool isFind;//当前岔路口是否被访问
};

//准备一个函数,用来判断当前坐标表示的位置是否可以通行
bool isCheckMove(PathNode p[][MAP_COL],int row,int col)
{
	if (row < 0 || row >= MAP_ROW || col < 0 || col >= MAP_COL)//越界判断
		return false;
	if (p[row][col].isFind == true || p[row][col].val != 0)//判断当前行列表示的坐标已经访问过,或者当前坐标上的值为表示障碍
		return false;
	return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int mapArr[MAP_ROW][MAP_COL] = {
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
		{ 1, 0, 0, 1, 1, 0, 0, 0, 0, 1 },
		{ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1 },
		{ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1 },
		{ 1, 1, 0, 0, 0, 0, 1, 1, 0, 1 },
		{ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1 },
		{ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1 },
		{ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 1, 1, 0, 1 },
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
	};

	PathNode pathArr[MAP_ROW][MAP_COL];
	for (int i = 0; i < MAP_ROW; ++i)
	{
		for (int j = 0; j < MAP_COL; ++j)
		{
			pathArr[i][j].val = mapArr[i][j];//把资源数组的岔路口的值赋值到辅助数组中
			pathArr[i][j].isFind = false;//地图中的每一个岔路口都没有被访问过
			pathArr[i][j].dir = p_up;//为每一个岔路口初始一个初始寻路方向
		}
	}

	//第6步:准备起点和终点
	MyPoint beginPoint = { 1, 2 };
	MyPoint endPoint = { 8, 8 };

	//第7步:准备一个栈容器来保存所有的路径点
	vector<MyPoint> ms;
	ms.push_back(beginPoint);//把起点压入容器

	//第8步:准备一个辅助的坐标变量。1、用来表示当前正在寻路的坐标值
	MyPoint currPoint = beginPoint;//最开始的辅助点就是起点,通过起点找第二个点,这个辅助点才会变成第二点的坐标

	//第9步:开始寻路
	while (true)//无法确定循环次数
	{
		switch (pathArr[currPoint.row][currPoint.col].dir)//判断一个初始方向
		{
		case p_up:
			pathArr[currPoint.row][currPoint.col].dir = p_left;//当前点的上方向不可通行,改当前点的下一次搜索方向
			if (isCheckMove(pathArr, currPoint.row - 1, currPoint.col))
			{
				//如果进入条件,表示该坐标是可通行的
				pathArr[currPoint.row][currPoint.col].isFind = true;//当前点改为已访问
				MyPoint tempPoint = { currPoint.row - 1, currPoint.col };
				ms.push_back(tempPoint);//把当前点的上方向可通行坐标压入容器
				currPoint = tempPoint;//把当前点的上方向可通行坐标赋值给当前坐标,以便于下一次从新的当前坐标开始查找
			}
			break;
		case p_left:
			pathArr[currPoint.row][currPoint.col].dir = p_down;//当前点的左方向不可通行,改当前点的下一次搜索方向
			if (isCheckMove(pathArr, currPoint.row, currPoint.col - 1))
			{
				//如果进入条件,表示该坐标是可通行的
				pathArr[currPoint.row][currPoint.col].isFind = true;//当前点改为已访问
				MyPoint tempPoint = { currPoint.row, currPoint.col - 1 };
				ms.push_back(tempPoint);//把当前点的左方向可通行坐标压入容器
				currPoint = tempPoint;//把当前点的左方向可通行坐标赋值给当前坐标,以便于下一次从新的当前坐标开始查找
			}
			break;
		case p_down:
			pathArr[currPoint.row][currPoint.col].dir = p_right;//当前点的下方向不可通行,改当前点的下一次搜索方向
			if (isCheckMove(pathArr, currPoint.row + 1, currPoint.col))
			{
				//如果进入条件,表示该坐标是可通行的
				pathArr[currPoint.row][currPoint.col].isFind = true;//当前点改为已访问
				MyPoint tempPoint = { currPoint.row + 1, currPoint.col };
				ms.push_back(tempPoint);//把当前点的下方向可通行坐标压入容器
				currPoint = tempPoint;//把当前点的下方向可通行坐标赋值给当前坐标,以便于下一次从新的当前坐标开始查找
			}
			break;
		case p_right:
			//注意:最后一个方向了,不需要再记录下一个方向,因为4方向搜索完成
			if (isCheckMove(pathArr, currPoint.row, currPoint.col + 1))
			{
				//如果进入条件,表示该坐标是可通行的
				pathArr[currPoint.row][currPoint.col].isFind = true;//当前点改为已访问
				MyPoint tempPoint = { currPoint.row, currPoint.col + 1 };
				ms.push_back(tempPoint);//把当前点的右方向可通行坐标压入容器
				currPoint = tempPoint;//把当前点的右方向可通行坐标赋值给当前坐标,以便于下一次从新的当前坐标开始查找
			}
			else
			{
				//证明当前点的4方向已经都不可通行,是死胡同
				//入栈的坐标是没有标记已经被访问的
				//MyPoint tempPoint = ms.getTop();
				pathArr[currPoint.row][currPoint.col].isFind = true;//在退栈之前,当前这个搜索的坐标标记为已经访问

				ms.pop_back();//当前点退栈,把当前这个表示死胡同的坐标退掉
				if (!ms.empty())//判断如果栈不为空
					currPoint = ms[ms.size()-1];//得到新的栈点元素
			}
			break;
		}
		//找到出口,没有出口 结束循环
		if (ms.empty())//没有路径,结束循环
			break;
		if (currPoint.row == endPoint.row && currPoint.col == endPoint.col)//当前点就是终点
			break;
	}

	//寻路终止,打印路径
	while (!ms.empty())
	{
		MyPoint tempPoint = ms[ms.size() - 1];
		//printf("row = %d\t col = %d\n",tempPoint.row,tempPoint.col);
		pathArr[tempPoint.row][tempPoint.col].val = 5;
		ms.pop_back();
	}

	for (int i = 0; i < MAP_ROW; ++i)
	{
		for (int j = 0; j < MAP_COL; ++j)
		{
			switch (pathArr[i][j].val)
			{
			case 5:
				printf("* ");
				break;
			default:
				printf("^ ");
			}
		}
		printf("\n");
	}

	return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值