A 寻路算法模拟实现 C++ 可运行
浅谈游戏中自动寻路算法的实现与应用

浅谈游戏中自动寻路算法的实现与应用作者:蒋恺来源:《中国新通信》 2018年第2期在信息技术的支持下,互联网进入了迅猛发展期,各种网游、页游大量出现,受到不同玩家的喜爱与青睐。
当然为了逐步扩大受众群,需要不断的优化游戏,满足玩家对游戏的需求,其中自动寻路算法就是十分关键的技术之一,提升了游戏角色在虚拟游戏环境中的灵活性,更利于对游戏角色的控制,是判断游戏质量的重要标准之一”1。
一、关于自动寻路算法的概述1.1自动寻路算法的原理在自动寻路算法中最常用的为A*算法,这属于启发式的算法,被广泛应用于游戏中的路径搜索【21。
主要是节点的设置,具有记录、搜索进度的功能,通过节点在游戏地图中移动,当搜寻到目标位置时就结算,否则会进一步搜索记录目标位置周围相邻的位置。
举例而言,游戏角色最初的位置就是开始节点,将要到达的目标位置设置为目标节点,在两者之间存在一定的障碍物和可以顺利通行的路径,黑色部分为障碍物,白色部分为可通行路径,具体如下图1所示:在设计A*算法时采用的基本原理,其实为最短路径算法,在整个游戏地图中,从起始节点到目标节点的路径多种多样,将这些全部读入到开放式列表中,再通过与目标节点距离最近的节点进行对比,从而找到最优路径”1。
将上图1中的起始节点设置为A,目标节点力B,在计算最优路径节点C时需要在考虑几何距离基础上使用计算公式:(A—C)2+fB—C)2在A*算法中通过对各个不同节点的计算,从而找出路径最短最优的节点,但这一算法具有一定的缺陷,很可能要将整个地图上的节点都计算完了才能得出结果,当游戏场景复杂且节点数量过多的话,会大大增加游戏设计制作中的寻路算法的费用。
为此,就要对A*算法进行优化改进,以便扩大应用范围,满足玩家的游戏需求。
1.2自动寻路算法的实现为了最快的找到游戏地图中的最优路径,需要将游戏场景进行网格划分,让每个网路成为大小相同的正方形,成为游戏中的导航网格,就可以选择一个节点起始位置,进行目标节点位置的广度搜索,在确定区域后在计算最佳路径。
C++DFS算法实现走迷宫自动寻路

C++DFS算法实现⾛迷宫⾃动寻路C++ DFS算法实现⾛迷宫⾃动寻路,供⼤家参考,具体内容如下深度优先搜索百度百科解释:事实上,深度优先搜索属于图算法的⼀种,英⽂缩写为DFS即Depth First Search.其过程简要来说是对每⼀个可能的分⽀路径深⼊到不能再深⼊为⽌,⽽且每个节点只能访问⼀次.运⾏效果:说明:深度优先搜索算法是在我在图的部分接触到的,后来才发现它也可以不⽤在图的遍历上,它是⼀个独⽴的算法,它也可以直接⽤在⼀个⼆维数组上。
其算法原理和实现步骤在代码中已经有了很好的体现了,这⾥就不再赘述。
在程序中实现了⼿动操控⾛迷宫和⾃动⾛迷宫两种模式,并且可在⾃动⾛完迷宫后显⽰⾏⾛的路径。
如果要修改程序使⽤的迷宫地图只需要修改map⼆维地图数组和两个地图宽⾼的常量值即可。
同样可以使⽤⾃动⾛迷宫的模式。
理论上这种算法可以对任意⼤⼩任意复杂的迷宫搜索路径,但是因为这种算法是⽤递归实现的,占⽤空间较⼤,地图⼤⼩增⼤也会多使⽤很多的空间,受限于堆栈空间的限制我在把地图⼤⼩增加到2020的时候运⾏⾃动寻路模式就会报堆栈溢出异常了。
我在代码准备了1818和15*15的两个迷宫地图⼆维数组⽤于测试。
编译环境:Windows VS2019代码:Game.h 游戏类#pragma once#include <iostream>#include <map>#include <conio.h>#include <vector>#include <windows.h>using namespace std;//地图宽⾼常量constexpr unsigned int mapWidth = 18;constexpr unsigned int mapHeight = 18;//游戏类class Game{private:map<int, string> cCMAEMap; //地图数组元素对应字符map<char, int*> movDistanceMap; //按键对应移动距离int px, py; //玩家坐标int dArr[4][2] = { {0, -1}, {0, 1}, {-1, 0}, {1, 0} }; //数值和移动⽅向对应数组vector<int*> tempPathVec; //路径向量vector<vector<int*>> allPathVec;//存储所有路径向量//检查参数位置是否可⾛bool check(int x, int y, int(*map)[mapWidth]){//判断修改后的玩家坐标是否越界、修改后的玩家坐标位置是否可⾛if (x < 0 || x >= mapWidth || y < 0 || y >= mapHeight || (map[y][x] != 0 && map[y][x] != 3)) return false;return true;}//控制玩家移动函数bool controlMove (int(*map)[mapWidth]){//键盘按下时if (!_kbhit()) return false;char key = _getch();if (key != 'w' && key != 's' && key != 'a' && key != 'd')return false;int temp_x = px, temp_y = py; //临时记录没有改变之前的玩家坐标px += movDistanceMap[key][0];py += movDistanceMap[key][1];//如果位置不可⾛则撤销移动并结束函数if (!check(px, py, map)){px = temp_x, py = temp_y;return false;}//判断是否已到达终点if (map[py][px] == 3){//打印信息并返回truecout << "胜利!" << endl;return true;}map[temp_y][temp_x] = 0; //玩家原本的位置重设为0路⾯map[py][px] = 2; //玩家移动后的位置设为玩家2//清屏并打印修改后地图system("cls");printMap(map);return false;}//⽤对应图形打印地图void printMap(int(*map)[mapWidth]){for (int i = 0; i < mapHeight; i++){for (int j = 0; j < mapWidth; j++)cout << cCMAEMap[map[i][j]];cout << endl;}}//初始化map容器void initMapContainer(){//数组元素和字符对应string cArr[4] = { " ", "■", "♀", "★" };for (int i = 0; i < 4; i++)cCMAEMap.insert(pair <int, string>(i, cArr[i]));//输⼊字符和移动距离对应char kArr[4] = { 'w', 's', 'a', 'd' };for (int i = 0; i < 4; i++)movDistanceMap.insert(pair <char, int*>(kArr[i], dArr[i]));}//找到玩家所在地图的位置void findPlayerPos(const int(*map)[mapWidth]){for (int i = 0; i < mapHeight; i++)for (int j = 0; j < mapWidth; j++)if (map[i][j] == 2){px = j, py = i;return;}}//深度优先搜索void dfs(int cx, int cy, int(*map)[mapWidth]){//把当前玩家位置插⼊到数组tempPathVec.push_back(new int[2] {cx, cy});//循环四个⽅向上下左右for (int i = 0; i < 4; i++){int x = cx + dArr[i][0]; //玩家下⼀个位置的坐标int y = cy + dArr[i][1];//检查下⼀个位置是否可⾛if (!check(x, y, map))continue;if (map[y][x] == 3) //已到达终点{tempPathVec.push_back(new int[2]{ x, y }); //把终点位置插⼊到向量中allPathVec.push_back(tempPathVec);return;}//为普通路径else{map[cy][cx] = -1; //当前位置临时设为-1,递归搜索时不可⾛原路,⾮0且⾮3的位置都不可⾛ dfs(x, y, map); //⽤下⼀个位置作为参数递归map[cy][cx] = 0; //递归完成后将当前位置重设为0,可⾛路径}}//最后没有找到可⾛的路径则删除向量最后⼀个元素,此时函数结束递归退回到上⼀层tempPathVec.pop_back();}//输出路径信息void printPathInformation(){//int minSizePathIndex = 0; //记录最短路径在路径向量中的下标//for (int i = 0; i < allPathVec.size(); i++)//{// cout << allPathVec.at(i).size() << " ";// if (allPathVec.at(i).size() < allPathVec.at(minSizePathIndex).size())// minSizePathIndex = i;//}//cout << endl << "最⼩长度:" << allPathVec.at(minSizePathIndex).size() << endl;输出最短路径信息//for (auto dArr2 : allPathVec.at(minSizePathIndex))// cout << dArr2[0] << "_" << dArr2[1] << " ";//输出所有路径信息//for (auto arr : allPathVec)//{// for (auto dArr2 : arr)// cout << dArr2[0] << "__" << dArr2[1] << " ";// cout << endl;//}}int findPath(int(*map)[mapWidth]){findPlayerPos(map); //找到玩家所在地图中的位置//如果多次调⽤findPaths函数,则需要先清除上⼀次调⽤时在向量中遗留下来的数据 tempPathVec.clear();allPathVec.clear();dfs(px, py, map); //找到所有路径插⼊到allPathVec//找到最短路径在allPathVec中的下标int minSizePathIndex = 0; //记录最短路径在路径向量中的下标for (int i = 0; i < allPathVec.size(); i++){if (allPathVec.at(i).size() < allPathVec.at(minSizePathIndex).size())minSizePathIndex = i;}return minSizePathIndex;}//显⽰路径void showPath(int(*map)[mapWidth], vector<int*> tempPathVec){//将能找到的最短的路径上的元素赋值全部赋值为2并输出for (auto tempDArr : tempPathVec)map[tempDArr[1]][tempDArr[0]] = 2;system("cls");printMap(map); //打印地图}//⼿动模式void manualMode(int(*map)[mapWidth]){while (!controlMove(map)) //游戏循环Sleep(10);}//⾃动模式void automaticMode(int(*map)[mapWidth]){//找到最短路径vector<int*> tempPathVec = allPathVec.at(findPath(map));for (int i = 1; i < tempPathVec.size(); i++){map[tempPathVec[i - 1][1]][tempPathVec[i - 1][0]] = 0;map[tempPathVec[i][1]][tempPathVec[i][0]] = 2;system("cls");printMap(map); //打印地图Sleep(200);}cout << "胜利!是否打印完整路径?(Y / N)" << endl;char key = _getch();if(key == 'Y' || key == 'y')showPath(map, tempPathVec);}public://构造Game(int(*map)[mapWidth], char mode){initMapContainer(); //初始化map容器findPlayerPos(map); //找到玩家所在地图中的位置system("cls");printMap(map); //先打印⼀遍地图♀■★(mode == '1') ? manualMode(map) : automaticMode(map);}//析构释放内存{for (auto it = tempPathVec.begin(); it != tempPathVec.end(); it++){delete* it;*it = nullptr;}tempPathVec.clear();//这⾥不会释放allPathVec了allPathVec.clear();}};迷宫.cpp main函数⽂件#include "Game.h"//光标隐藏void HideCursor(){CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); }int main(){HideCursor(); //光标隐藏//0空地,1墙,2⼈, 3出⼝//int map[mapHeight][mapWidth] = {// 2, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1,// 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1,// 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0,// 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1,// 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,// 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0,// 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0,// 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,// 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0,// 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0,// 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1,// 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1,// 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,// 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0,// 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 3,//};int map[mapHeight][mapWidth]{2, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1,0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1,1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0,1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0,1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1,0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1,0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1,0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0,0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1,1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0,0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1,1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1,1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0,0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1,0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1,1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0,1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 3,};//复制⼀个⼀样的数组以保证重新开始游戏时可以重置数组int mapCopy[mapHeight][mapWidth];memcpy(mapCopy, map, sizeof(mapCopy));while (true){cout << "选择模式:1,⼿动 2,⾃动" << endl;char key = _getch();Game game(mapCopy, key); //进⼊游戏cout << "输⼊r重新开始:" << endl;key = _getch();if (key != 'r' && key != 'R') //输⼊值不为r则结束程序break;memcpy(mapCopy, map, sizeof(mapCopy)); //重新赋值system("cls");}return 0;}以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
C++八方向Astar寻路算法大作业

#define col 27
using namespace std;
const int direction[8][2] = { { -1,-1 },{ -1,0 },{ -1,1 },{ 0,-1 },{ 0,1 },{ 1,-
1 },{ 1,0 },{ 1,1 } };// 方向
enum { virable, wall, inOpen, inClose, start, goal };
{
if (tempPoint->parent->r-tempPoint->r == 1 && tempPoint->parent->c == tempPoint->c)
map[tempPoint->parent->r][tempPoint->parent->c] = 4;
if (tempPoint->parent->r-tempPoint->r == -1 && tempPoint->parent->c == tempPoint->c)
1)
map[tempPoint->parent->r][tempPoint->parent->c] = 8;
if (tempPoint->parent->r-tempPoint->r == -1 && tempPoint->parent->c - tempPoint->c ==
1)
map[tempPoint->parent->r][tempPoint->parent->c] = 9;
temp->openPoint = point;
单源最短路径dijkstra算法c语言

单源最短路径dijkstra算法c语言单源最短路径问题是图论中的经典问题之一,指的是在图中给定一个起始节点,求出该节点到其余所有节点之间的最短路径的算法。
其中,Dijkstra 算法是一种常用且高效的解决方案,可以在有向图或无向图中找到起始节点到其余所有节点的最短路径。
本文将逐步介绍Dijkstra算法的思想、原理以及C语言实现。
一、Dijkstra算法的思想和原理Dijkstra算法的思想基于贪心算法,通过逐步扩展当前已知路径长度最短的节点来逐步构建最短路径。
算法维护一个集合S,初始时集合S只包含起始节点。
然后,选择起始节点到集合S之外的节点的路径中长度最小的节点加入到集合S中,并更新其他节点的路径长度。
具体来说,算法分为以下几个步骤:1. 初始化:设置起始节点的路径长度为0,其他节点的路径长度为无穷大。
2. 选择最小节点:从集合S之外的节点中选择当前路径长度最短的节点加入到集合S中。
3. 更新路径长度:对于新加入的节点,更新与其相邻节点的路径长度(即加入新节点后的路径长度可能更小)。
4. 重复步骤2和3,直到集合S包含所有节点。
二、Dijkstra算法的C语言实现下面我们将逐步讲解如何用C语言实现Dijkstra算法。
1. 数据结构准备首先,我们需要准备一些数据结构来表示图。
我们可以使用邻接矩阵或邻接表来表示图。
这里,我们选择使用邻接矩阵的方式来表示权重。
我们需要定义一个二维数组来表示图的边权重,以及一个一维数组来表示起始节点到各个节点的路径长度。
c#define MAX_NODES 100int graph[MAX_NODES][MAX_NODES];int dist[MAX_NODES];2. 初始化在使用Dijkstra算法之前,我们需要对数据进行初始化,包括路径长度、边权重等信息。
cvoid initialize(int start_node, int num_nodes) {for (int i = 0; i < num_nodes; i++) {dist[i] = INT_MAX; 将所有节点的路径长度初始化为无穷大}dist[start_node] = 0; 起始节点到自身的路径长度为0初始化边权重for (int i = 0; i < num_nodes; i++) {for (int j = 0; j < num_nodes; j++) {if (i == j) {graph[i][j] = 0; 自身到自身的边权重为0} else {graph[i][j] = INT_MAX; 其他边权重初始化为无穷大}}}}3. 主要算法接下来是Dijkstra算法的主要逻辑。
c语言最短路径搜寻算法

c语言最短路径搜寻算法
C 语言最短路径搜寻算法常用于在网图中寻找两点之间的最短路径,其中网图的最短路径分为单源最短路径和多源最短路径。
以下是两种常见的最短路径搜寻算法:- Dijkstra 算法:从一个起始点出发,到达一个终点,通过对路径权值的累加,找到最短路径。
- Floyd 算法:对于网中的任意两个顶点来说,之间的最短路径不外乎有两种情况。
一种是直接从一个顶点到另一个顶点的边的权值;另一种是先经过若干个顶点,最终达到另一个顶点,期间经过的边的权值和。
这两种算法都可以用 C 语言实现,你可以根据具体需求选择合适的算法。
若你想了解更多关于最短路径搜寻算法的内容,可以继续向我提问。
浅谈寻路A算法范文

浅谈寻路A算法范文寻路算法(Pathfinding)是计算机中常用的一种算法,通过图形结构中两个节点之间的最佳路径,解决了很多实际问题,如游戏中的NPC寻路、自动驾驶的路径规划等。
其中,A*算法(A-star algorithm)被广泛应用于寻路算法中,本文将对A*算法进行详细介绍。
A*算法是通过启发式算法(Heuristic Search)实现的一种寻路算法,根据估算函数(Heuristic Function)对节点进行评估,并选择具有最小开销的节点进行扩展。
A*算法的核心思想是综合考虑节点的实际开销(G 值)和预估的目标开销(H值),并选择最优节点进行。
在A*算法中,节点的开销是通过计算路径上节点的实际开销和预估开销得到的。
实际开销是指从起始节点到当前节点的移动开销,通常是节点间的距离或代价。
预估开销是通过估算函数对当前节点到目标节点的距离进行评估,常用的估算函数有欧几里得距离、曼哈顿距离等。
A*算法的具体步骤如下:1. 创建一个开启列表(Open List)和一个关闭列表(Closed List),起始节点放入开启列表。
2.从开启列表中选出具有最小开销的节点作为当前节点,并将其放入关闭列表中。
3.对当前节点的所有相邻节点进行遍历,如果该节点不可通过或者在关闭列表中,则忽略。
4.计算相邻节点的实际开销和预估开销,更新节点的G值和H值。
5.如果相邻节点不在开启列表中,将其加入开启列表,并将当前节点设置为该节点的父节点。
6.如果相邻节点已经在开启列表中,比较当前节点作为父节点时的G 值和之前的G值,如果小于之前的G值,更新节点的父节点为当前节点。
7.重复2-6步骤,直到达到目标节点或者开启列表为空。
8.如果达到目标节点,从目标节点开始回溯父节点,得到最佳路径。
A*算法的优势在于通过使用估算函数,能够快速找到目标节点,而且能够保证找到的路径是最佳路径。
同时,A*算法可以通过调整估算函数的权重来权衡的速度和路径的质量。
A算法的实现原理及应用

A算法的实现原理及应用算法是计算机科学中重要的概念,其本质是一种数学思想,是一系列求解问题的方法和步骤。
A算法,也称为A*算法,是一种常见的寻路算法,被广泛应用于游戏开发、人工智能、机器人控制等领域。
本文将介绍A算法的实现原理及其应用。
一、A算法的实现原理A算法是一种搜索算法,其目标是在搜索图中找到从起点到终点的最短路径。
A算法基于一种启发式搜索策略,即优先考虑最有可能通向终点的节点。
下面是A算法的基本实现步骤:1. 初始化开始节点和结束节点,并把开始节点加入到开启列表中。
2. 从开启列表中选出具有最小f值(f值是节点的启发值和代价值之和)的节点作为当前节点。
3. 把当前节点从开启列表中删除,并将其加入到关闭列表中。
4. 遍历当前节点的相邻节点,如果相邻节点不可通过或者已经在关闭列表中,就忽略。
5. 对于未被遍历过的相邻节点,计算它的f值、g值和h值。
其中,g值表示从起点到该节点的代价,h值表示该节点到终点的启发值,即估算到终点的实际代价。
6. 如果相邻节点已经在开启列表中,比较新的g值和原先的g值,如果新的g值更小,就更新g值和f值。
如果相邻节点不在开启列表中,将其加入到开启列表中,并计算其f、g、h值。
7. 重复步骤2到步骤6,直到找到终点或者开启列表为空。
二、A算法的应用A算法是一种高效的寻路算法,其应用非常广泛。
下面列举几个例子:1. 游戏开发在游戏开发中,A算法被广泛用于计算游戏场景中的敌人或角色行走的最佳路径。
游戏场景通常被表示为一个二维数组,A算法可以根据玩家角色的位置和目标位置,在场景图中寻找最短路径,并输出路径。
2. 人工智能A算法是人工智能领域中常用的算法之一,可以被用于求解最优路径问题。
例如,在机器人路径规划中,A算法可以根据机器人的当前位置和目标位置,搜索机器人的最短路径,并输出路径。
3. 网络路由A算法也被广泛应用于网络路由领域。
当网络中出现路由选择问题时,A算法可以根据网络拓扑结构和路由代价,寻找到源节点到目标节点的最短路径。
简单寻路算法

简单寻路算法在⽂中可能会出现⼀些专业术语或者是我信⼝雌黄的话语,未免看官不明⽩,前⾯我先加以注解,具体意思可以从⽂中体会到该寻路算法是在⼀个由很多⽅格组成的图像中,你操纵⼀个蓝⾊⼩⽅格进⾏寻路的环境下进⾏讲解,具体请看⽂章⼀开始的flash⽰例,或者是查看⽅格:⼀个⼀个的⼩⽅块障碍物:挡着去路的东西⽬标⽅格:你想到达的⽅格操控⽅格:你控制的寻路对象标记:临时为某⼀个⽅格做的标记⽗标记:除了操控⽅格所创建的临时标记,每个标记都有个⽗标记,但⽗标记不是随便乱定的,请看下⽂开启标记列表:当该标记还未进⾏过遍历,会先加⼊到开启标记列表中关闭标记列表:当该标记已经进⾏过遍历,会加⼊到关闭标记列表中路径评分:通过某种算法,计算当前所遍历的标记离⽬标⽅格的路径耗费估值(后⾯会讲⼀种通⽤的耗费算法) ⾸先描述⼀个环境,在⼀望⽆际的⽅格中,我⾝处某某⽅格,如今我想去某某⽅格,接下来我开始寻路! 在脑海中,先创建开启标记列表、关闭标记列表,然后把我的初始位置设置为开始标记进⾏遍历,同时因为开始标记已经遍历过了,因此把开始标记加⼊到关闭列表。
通过开始标记我们找出了相邻的⼋个⽅格,为它们创建相应的标记,加⼊到开启标记列表中,并把每个标记的⽗标记设置为开始标记,是因为开始标记才让我们这些⽅格创建了属于⾃⼰的标记,它就是我们的再⽣⽗母。
但不符合条件的我们就不加⼊开启标记列表(下⾯的条件符合任何⼀条都不要加⼊到开启标记列表中): 1、它在我们的搜寻地图范围外,⽐如你地图的寻路范围是 0*0 - 50*50,那么但这个点在边缘的时候,那它相邻的⼋个⽅格,必定有⼏个是处在外⾯的! 2、搜寻的这个⽅格是否有障碍物、或不可到达,⽐如河流,⽯头,⼭川等 3、判断它是否已经加⼊关闭标记列表,若已经加⼊表⽰该⽅格已经遍历过了,在遍历⼀次也⽆济于事,还会影响效率 4、判断它是否已经加⼊开启标记列表,若已经加⼊那么咋们就来判断⼀下该标记是否离开始标记更近⼀些 5、判断当斜着⾛的时候,它的上下或左右是否有障碍,如果有则表⽰你⽆法斜着⾛,需要先横⾛⼀下,再竖⾛⼀下或者是竖⾛⼀下,再横⾛⼀下 如果想象不出来,可以看着这个进⾏学习和⽐较。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
////////////////////////////////////////////////////////////////////////// //////////写一个自己实现的A*搜索算法////////////////////////////////////////////////////////////////////////// #include"stdafx.h"#include<iostream>#include<vector>#include<map>#include<algorithm>#include<assert.h>using namespace std;const int nMapWidth = 8;const int nMapHeight = 8;struct Node{int nEnable;int nNodeMark;int nValue;int x;int y;Node():nEnable(0),nNodeMark(0),nValue(0),x(0),y(0){};};std::map<int ,int > m_OpenList;std::map<int ,int > m_CloseList;std::vector<int> m_KeyList;Node m_MapNode[nMapWidth][nMapHeight];//计算openlist中靠前节点周围的节点void ComputerRound(int curx,int cury);//将一个新的节点加入到OPenList中void AddNodeToOpenList(Node* pNode,int nNum);//打印地图void Print(Node pNode[][nMapHeight]);void Print(Node pNode[][nMapHeight]){for (int n = 0; n < nMapWidth; ++n){for(int m = 0; m < nMapHeight; ++m){if (m == 0)cout<<endl;if (n == 0)cout<<pNode[n][m].nEnable/*<<"("<<" "<<pNode[n][m].nNodeMark<<")"*/<<" ";elsecout<<pNode[n][m].nEnable/*<<"("<<pNode[n][m].nNodeMark<<")"*/<<" ";}}}//将一个新的节点加入到OPenList中void AddNodeToOpenList(Node* pNode,int nNum){if(!pNode || !(pNode->nEnable))return;if (m_OpenList.empty()){m_OpenList[pNode->nNodeMark] = nNum;m_KeyList.push_back(pNode->nNodeMark);}else{std::map<int,int>::iterator itr = m_OpenList.find(pNode->nNodeMark);if (itr == m_OpenList.end()){std::map<int,int>::iterator itrQ = m_CloseList.find(pNode->nNodeMark);if (itrQ != m_CloseList.end()){if (nNum < (*itrQ).second){m_CloseList.erase(itrQ);}elsereturn;}else{m_OpenList[pNode->nNodeMark] =nNum;m_KeyList.push_back(pNode->nNodeMark);}}else{if ((*itr).second > nNum){m_OpenList[pNode->nNodeMark] =nNum;}}}}//将openlist中的一个靠前的节点展开到CloseList中void AddNodeToCloseList(Node* pNode,int nNum){if(!pNode)return;if (m_CloseList.empty()){m_CloseList[pNode->nNodeMark] = nNum;ComputerRound(pNode->x,pNode->y);}else{std::map<int,int>::iterator itrB = m_CloseList.find(pNode->nNodeMark);if(itrB == m_CloseList.end()){std::map<int,int>::iterator itrO = m_OpenList.find(pNode->nNodeMark);if (itrO != m_OpenList.end()){if ((*itrO).second < nNum){return;}else{std::vector<int>::iterator itrK =std::find(m_KeyList.begin(),m_KeyList.end(),(*itrO).first);if (itrK != m_KeyList.end())m_KeyList.erase(itrK);m_OpenList.erase(itrO);}}else{m_CloseList[pNode->nNodeMark] += nNum;ComputerRound(pNode->x,pNode->y);}}else{if (nNum < m_CloseList[pNode->nNodeMark])m_CloseList[pNode->nNodeMark] = nNum;}}}//探索是否该节点可行void TryNode(int nx,int ny,int curx, int cury){if (nx < 0 || ny < 0 || nx >= nMapWidth || ny >= nMapWidth)return;if (m_MapNode[nx][ny].nEnable == 0)return;int nNum = abs(nx - curx) + abs(ny - cury);std::map<int,int>::iterator itr = m_CloseList.find(m_MapNode[curx][cury].nNodeMark);if(itr != m_CloseList.end())nNum += (*itr).second;AddNodeToOpenList(&(m_MapNode[nx][ny]),nNum);}#define DesX 3#define DesY 4void ComputerRound(int curx,int cury){//对每一个当前节点执行以下操作TryNode(curx,cury+1,curx,cury);TryNode(curx+1,cury,curx,cury);TryNode(curx+1,cury+1,curx,cury);TryNode(curx-1,cury,curx,cury);TryNode(curx-1,cury-1,curx,cury);TryNode(curx-1,cury+1,curx,cury);TryNode(curx,cury-1,curx,cury);TryNode(curx+1,cury-1,curx,cury);}void main(){int nMark = 0;for (int n = 0; n < nMapWidth; ++n){for(int m = 0; m < nMapHeight; ++m){if (n != 2 || m == 3 || m == 1)m_MapNode[n][m].nEnable = 1;if (n == 4 && (m != 6))m_MapNode[n][m].nEnable = 0;m_MapNode[n][m].nNodeMark = ++nMark;m_MapNode[n][m].x = n;m_MapNode[n][m].y = m;}}Print(m_MapNode);AddNodeToCloseList(&(m_MapNode[1][1]),0);std::map<int,int>::iterator itr;while(!m_KeyList.empty()){itr = m_OpenList.find(*(m_KeyList.begin()));int nV = (*itr).first;int nNum =(*itr).second;std::vector<int>::iterator itrK =std::find(m_KeyList.begin(),m_KeyList.end(),(*itr).first);if (itrK != m_KeyList.end())m_KeyList.erase(itrK);itr = m_OpenList.erase(itr);AddNodeToCloseList(&(m_MapNode[(nV-1)/nMapWidth][(nV-1)%nMapWidth]),nNum);}cout<<endl;cout<<endl;std::map<int,int>::iterator itrC;for (int n = 0; n < nMapWidth; ++n){for(int m = 0; m < nMapHeight; ++m){if (m == 0)cout<<endl;if (m == 1 && n == 1){cout<<"ST"<<" ";continue;}itrC = m_CloseList.find(m_MapNode[n][m].nNodeMark);if (itrC != m_CloseList.end()){cout<<(*itrC).second<<" ";}elsecout<<"0"<<" ";}}getchar();}。