游戏中寻路算法
方法一:广度优先搜索算法
//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|