欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构学习第十八课(寻路算法之深度寻路)

程序员文章站 2022-03-08 11:54:20
...

寻路算法

/*
寻路算法:
找路径

1 深度寻路:不一定能找到最短路径,回退,循环较少,步骤简单,适用于空旷地图;只能走直线
2 广度寻路:一定能找到最短路径,不需要回退,循环较多,步骤复杂,适用于较小的复杂地图;只能走直线
3 A星寻路:一定能找到最短路径,不需要回退,循环较少,但需要提前设计好代价;只能走斜线
*/

1,深度寻路

1.1头文件
#pragma once
#include<string.h>
template<typename T>
class MyStack
{
private:
	T* pRoot;
	int len;
	int maxLen;
public:
	MyStack() 
	{
		pRoot = NULL;
		len = 0;
		maxLen = 0;
	}
	~MyStack()
	{
		if (pRoot)
		{
			delete[] pRoot;
		}
		pRoot = NULL;
		len = 0;
		maxLen = 0;
	}
	//入栈
	void push(const T& data);
	//判空
	bool isEmpty()const
	{
		return (len == 0);
	}
	//出栈
	void pop() { len--; };
	//获取栈顶元素
	T GetTop()const
	{
		return pRoot[len - 1];
	}

};

template<typename T>
void MyStack<T>::push(const T& data)
{
	if (len <= maxLen)
	{
		maxLen = maxLen + (((maxLen >> 1) > 1) ? (maxLen >> 1) : 1);
		T* pTemp = new T[maxLen];
		memcpy(pTemp, pRoot, sizeof(T) * len);
		delete[] pRoot;
		pRoot = pTemp;
	}
	pRoot[len++] = data;

}

2.2源文件


/*
深度寻路思想:
1 记录当前点当前试探方向
试探方向顺序:一般:逆时针(上左下右) / 顺时针(上右下左);
2 记录当前点是否走过
2.1 每走过一步,入栈
2.2 需要回退的时候 死胡同时 回退
2.2.1 删除栈顶元素
2.2.2 跳到当前栈顶元素的位置
*/

#include<stdio.h>
#include<stack>
#include<graphics.h>
#include"Mystack.h"
#define SPACE 50
 
using namespace std;
#define ROW 12
#define COL 12
//地图中元素类型
enum type{p_road,p_wall};
//方向
enum dirc{p_up,p_down,p_left,p_right};
//描述一个点
struct Point
{
	int row;
	int col;
	bool operator==(const Point& p)
	{
		if (this->row == p.row && this->col == p.col)
		{
			return true;
		}
		return false;
	}
};
//辅助地图结点类型
struct pathNode
{
	int dir;//当前试探方向
	bool isFind;//是否走过
};
IMAGE wall, ren, road, pos;
void printMap(Point pos, int map[ROW][COL]);
void showMap(Point pos, int map[ROW][COL]);
int main()
{
	initgraph(COL * SPACE, ROW * SPACE, SHOWCONSOLE);
	loadimage(&wall, "wall.bmp", SPACE, SPACE, true);
	loadimage(&ren, "ren.bmp", SPACE, SPACE, true);
	loadimage(&road, "road.bmp", SPACE, SPACE, true);
	loadimage(&pos, "pos.bmp", SPACE/2, SPACE/2, true);
	
	
	//1 描述地图
	int map[ROW][COL] =
	{
		{1,1,1,1,1,1,1,1,1,1,1,1},
		{1,0,1,1,0,1,1,1,1,0,0,1},
		{1,0,1,1,0,0,0,1,1,0,1,1},
		{1,0,1,1,0,1,0,1,1,0,1,1},
		{1,0,1,1,0,1,0,1,1,0,1,1},
		{1,0,1,1,0,1,0,1,1,0,1,1},
		{1,0,1,1,0,1,0,0,1,0,1,1},
		{1,0,1,1,0,1,1,0,1,0,1,1},
		{1,0,0,0,0,1,1,0,1,0,1,1},
		{1,0,1,1,0,1,1,0,1,0,1,1},
		{1,0,1,1,0,1,1,0,0,0,1,1},
		{1,1,1,1,1,1,1,1,1,1,1,1}
	};
	//2 记录当前点当前试探方向,是否走过
	pathNode pathMap[ROW][COL] = { 0 };

	//3 起点 终点
	bool isFindEnd = false;
	Point begPos = { 1,1 };
	Point endPos = { 1,10 };

	//4 栈
	MyStack<Point> stack;

	//5 标记起点走过的,起点入栈
	stack.push(begPos);
	pathMap[begPos.row][begPos.col].isFind = true;
	//6 寻路
	Point curPos = begPos;
	Point serPos;
	while (1)
	{
		//6.1确定试探点
		serPos = curPos;//先将试探点设置为当前点
		switch (pathMap[curPos.row][curPos.col].dir)
		{
		case p_up:
			serPos.row--;//根据当前点当前试探方向,确定试探点
			//当前点当前试探方向改变
			pathMap[curPos.row][curPos.col].dir = p_down;
			if (pathMap[serPos.row][serPos.col].isFind == false &&//没走过
				map[serPos.row][serPos.col] == p_road)//有路
			{
				//能走
				//走
				curPos = serPos;
				//标记走过
				pathMap[curPos.row][curPos.col].isFind = true;
				//入栈
				stack.push(curPos);
			}
			break;
		case p_down:
			serPos.row++;//根据当前点当前试探方向,确定试探点
			//当前点当前试探方向改变
			pathMap[curPos.row][curPos.col].dir = p_left;
			if (pathMap[serPos.row][serPos.col].isFind == false &&//没走过
				map[serPos.row][serPos.col] == p_road)//有路
			{
				//能走
				//走
				curPos = serPos;
				//标记走过
				pathMap[curPos.row][curPos.col].isFind = true;
				//入栈
				stack.push(curPos);
			}
			break;
		case p_left:
			serPos.col--;//根据当前点当前试探方向,确定试探点
			//当前点当前试探方向改变
			pathMap[curPos.row][curPos.col].dir = p_right;
			if (pathMap[serPos.row][serPos.col].isFind == false &&//没走过
				map[serPos.row][serPos.col] == p_road)//有路
			{
				//能走
				//走
				curPos = serPos;
				//标记走过
				pathMap[curPos.row][curPos.col].isFind = true;
				//入栈
				stack.push(curPos);
			}
			break;
		case p_right:
			serPos.col++;//根据当前点当前试探方向,确定试探点
			if (pathMap[serPos.row][serPos.col].isFind == false &&//没走过
				map[serPos.row][serPos.col] == p_road)//有路
			{
				//能走
				//走
				curPos = serPos;
				//标记走过
				pathMap[curPos.row][curPos.col].isFind = true;
				//入栈
				stack.push(curPos);
			}
			else
			{
				//死胡同
				//删除栈顶元素
				stack.pop();
				//跳到当前栈顶元素
				curPos = stack.GetTop();
			}
			break;
		}
		printMap(curPos, map);
		showMap(curPos, map);
		//判断到没到终点
		if (curPos == endPos)
		{
			isFindEnd = true;
			break;
		}
		//判断是否回到起点
		if (stack.isEmpty())
			break;
	}
	if (isFindEnd)
	{
		printf("找到了终点!!!\n");
		while (!stack.isEmpty())
		{
			printf("(%d %d)", stack.GetTop().row,
				stack.GetTop().col);
			putimage(stack.GetTop().col * SPACE
				+SPACE/3,
				stack.GetTop().row * SPACE + SPACE / 3,
				&pos);
			stack.pop();
		}
		printf("\n");
	}
	else
	{
		printf("没找到终点!!!\n");
	}
	while (1);
	return 0;
}

void printMap(Point pos, int map[ROW][COL])
{
	system("cls");
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			if (pos.row == i && pos.col == j)
			{
				printf("人");
			}
			else if(p_road==map[i][j])
			{
				printf("  ");
			}
			else
			{
				printf("墙");
			}
		}
		printf("\n");
	}
}

void showMap(Point pos, int map[ROW][COL])
{
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			if (pos.row == i && pos.col == j)
			{
				putimage(j * SPACE, i * SPACE, &ren);
			}
			else if (p_road == map[i][j])
			{
				putimage(j * SPACE, i * SPACE, &road);
			}
			else
			{
				putimage(j * SPACE, i * SPACE, &wall);
			}
		}
		printf("\n");
	}
}