游戏中寻路算法

游戏中寻路算法
方法一:广度优先搜索算法
//bfs寻路算法 确定也明显 没有像 迪杰斯特拉算法中的最短路径一样。也就是没有权值不能找到最短的

代码

//bfs寻路算法  确定也明显 没有像 迪杰斯特拉算法中的最短路径一样。也就是没有权值,不能找到最短的

//used[temp_i][temp_j] = true;  bfs没有对应的 false这是和bfs不一样的
#include<iostream>
#include<vector>
#include<queue>
using namespace std;


#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;



class Solution {
private:


	vector<vector<int>> dxy{ {0,1},{1,0},{0,-1}, {-1,0} };//走的方向依次是  右下左上
	bool isArea(vector<vector<int>> &maze, int temp_x, int temp_y)
	{
		if (temp_x < 0 || temp_x >= maze.size() || temp_y < 0 || temp_y >= maze[0].size())  return false;


		return true;

	}




public:
	int getShortpath(vector<vector<int>> &maze, int start_i, int start_j, int target_i, int target_j)  //maze中0代表可走,1代表是障碍物
	{
		vector<vector<bool>> used(maze.size(), vector<bool>(maze[0].size(), false));


		if (isArea(maze, start_i, start_j) && used[start_i][start_j] == false)//这里防止刚开始位置越界
		{

			used[start_i][start_j] = true;

			int step = 0;
			queue<pair<int, int>> qu;
			qu.emplace(start_i, start_j);


			while (!qu.empty())
			{

				int n = qu.size();
				for (int i = 0;i < n;i++)
				{
					auto node = qu.front();
					qu.pop();//一定记得pop
					int current_i = node.first;
					int current_j = node.second;
					//cout << "current_i=" << current_i << "  current_j=" << current_j  << "  step="<< step << endl;
					if (current_i == target_i && current_j == target_j)
					{

						return  step;
					}

					for (int i = 0;i < dxy.size();i++)
					{

						int temp_i = current_i + dxy[i][0];
						int temp_j = current_j + dxy[i][1];


						if (isArea(maze, temp_i, temp_j) && maze[temp_i][temp_j] == 0 && used[temp_i][temp_j] == false)
						{
							cout << "temp_i=" << temp_i << "  temp_j=" << temp_j << "  step=" << step << endl;
							used[temp_i][temp_j] = true;


							qu.emplace(temp_i, temp_j);



						}

					}



				}
				cout << "*******************" << endl;
				for (int i = 0;i < used.size();i++)
				{
					for (int j = 0;j < used[0].size();j++)
					{
						cout << used[i][j] << "  ";
					}
					cout << endl;

				}
				cout << endl;
				cout << "*******************" << endl;
				step++;


			}


		}


		return INT_MAX;
	}
};


int main()
{
	vector<vector<int>>  maze
	{
	{0,0,1,0},
	{0,0,0,0},
	{0,0,1,0},
	{0,1,0,0},
	{0,0,0,1} };
	int start_i = 0;
	int start_j = 0;
	int target_i = 3;
	int target_j = 2;
	Solution s;
	int path = s.getShortpath(maze, start_i, start_j, target_i, target_j);
	cout << "path=" << path << endl;

}

题目:
迪杰斯特拉算法 可以找到所有的节点最短路径,
求以某一起始点到另外所有结点的最短路径dist
在这里插入图片描述

思路:

首先对应的二维矩阵是在这里插入图片描述

其次我们需要明白 迪杰斯特拉(Dijkstra)是针对连通图来说的。
代码最重要的两个变量

		vector<int> visit(n,0);//0代表未访问节点,1代表访问节点


		vector<int> dist(n, 0);//后面会根据start进行初始化,这里初始化值是任何值都没关系


主要思路是,首先将start节点先拎出来,然后每次将最小的dist的没有访问的节点找到作为中转节点,然后以中转节点更新,dist的从起始节点到非访问节点的更小值。
代码:

//单源最短路径,迪杰斯特拉算法

//总体思路,是将每次最短的还没有访问的节点作为中转节点,然后从寻找从中转节点到其他节点和之前的到start的节点路径作比较,
//更新每个未访问节点的最短路径,将中转节点设置成访问节点,进入下一次循环。
#include<iostream>
#include<vector>

#define INF  999999//路径中不可达边  因此graph也应该这么写不可达边的长度

using namespace std;

class Solution {
public:
	vector<int> Dijkstra(vector<vector<int>>& graph,int start)
	{
		int n = graph.size();
		vector<int> visit(n,0);//0代表未访问节点,1代表访问节点


		vector<int> dist(n, 0);//后面会根据start进行初始化,这里初始化值是任何值都没关系



		//首先将第一个start节点的信息提取出来,为循环做出准备
		if (start>=n)
		{
			cout << "起点位置不合法" << endl;
			return  dist;
		}
		visit[start] = 1;//  设置起点位置已访问1
		for (int i=0;i<n;i++)//设置起点位置为初始位置,初始化dist
		{
			dist[i] = graph[start][i];
		}


		for (int i=1;i<n;i++)//第一个节点已经单独拎出来了个节点,所以我们需要循环n-1次
		{
			int minNumber = INF;

			int mind=1111;//我们从这里可以看出无论此处mind初始值是多少,如果不是连通图,可能会造成,死循环, 因此使用该算法的图应该是连通图 
			
			
			for (int j=0;j< dist.size();j++)//寻找中转节点  记住当前中转节点一定是未访问节点
			{
				if (visit[j]==0&& minNumber> dist[j])
				{
					minNumber = dist[j];
					mind = j;
				}
			}
			
			//cout << "mind=" << mind << endl;
			//visit[mind] = 1;  //这个放在这里也是可以的


			//中转节点找到后,我们需要更新当前以中转节点和原点的  到其他非访问节点距离  
			for (int j=0;j<n;j++)//这里的j代表着节点的下标的意思
			{
				if (visit[j]==0&&dist[j]>dist[mind]+graph[mind][j])//这一步说明了graph中不能有INT_MAX不然可能会溢出
				{
					dist[j] = dist[mind] + graph[mind][j];
				}
			}

			
			visit[mind] = 1;//应该将中转节点设置成已访问
		}

		return dist;
	}
};

int main()
{
	int n = 6;
	vector<vector<int>> graph(n, vector<int>(n, INF));


	for (int i=0;i<n;i++)
	{
		graph[i][i] = 0;
	}


	graph[0][1] = 100;
	graph[1][0] = 100;


	graph[0][2] = 1200;
	graph[2][0] = 1200;

	graph[1][2] = 900;
	graph[2][1] = 900;

	graph[1][3] = 300;
	graph[3][1] = 300;

	graph[2][3] = 400;
	graph[3][2] = 400;

	graph[2][4] = 500;
	graph[4][2] = 500;

	graph[3][4] = 1300;
	graph[4][3] = 1300;

	graph[3][5] = 1400;
	graph[5][3] = 1400;

	graph[4][5] = 1500;
	graph[5][4] = 1500;

	Solution s;
	vector<int> dist;

	for (int j=0;j<n;j++)
	{
		cout << "以索引值为start=" << j << "设置为起始点" << endl;
		dist = s.Dijkstra(graph, j);


		
		for (int i = 0;i < n;i++)
		{
			cout << "  " << dist[i];
		}
		cout << endl;

	}


	

}

结果:

在这里插入图片描述

缺点:
迪杰斯特拉算法在寻路的网格中是无目的性的,

方式三:
**A*算法,**可以确定最短路径(总代价最小) 总代价=当前代价+预估代价

当前代价:我们可以使用 当前位置到起点位置的步数
预估代价,说明不是一个确切的数字,我们可以使用 曼哈顿距离 表示当前位置和目标位置 这两个坐标的绝对值差的和 即|x1-x2|+|y1-y2|

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值