0

0

c++如何实现A*寻路算法_c++游戏开发常用算法【源码】

穿越時空

穿越時空

发布时间:2025-12-26 10:02:43

|

549人浏览过

|

来源于php中文网

原创

A*寻路算法是C++游戏开发中最常用、最实用的路径搜索算法,适用于网格地图或图结构,兼顾效率与最优性;核心用优先队列(按f=g+h排序)、哈希表(查重与父节点映射),启发式推荐曼哈顿距离(4向)或对角距离(8向)。

c++如何实现a*寻路算法_c++游戏开发常用算法【源码】

在C++游戏开发中,A*(A-star)寻路算法是最常用、最实用的路径搜索算法之一。它兼顾效率与最优性,适合网格地图(如2D方格、Tile地图)或图结构中的单位移动规划。下面直接给出一个轻量、可读性强、带注释的C++实现,基于标准库,不依赖第三方引擎,可直接集成进你的游戏项目。

核心数据结构设计

要高效运行A*,需三个关键容器:

  • 开放列表(open set):待评估节点,用std::priority_queue(最小堆),按 f(n) = g(n) + h(n) 排序
  • 关闭列表(closed set):已处理节点,用std::unordered_set(哈希表)快速查重
  • 父节点映射(came_from):用std::unordered_map记录每个节点的前驱,用于回溯路径

启发式函数 h(n) 的选择

对网格地图,推荐使用曼哈顿距离(4向移动)或欧几里得距离(8向/斜向移动)。避免用错导致非最优或变慢:

  • 4方向(上下左右)→ 用曼哈顿:abs(x1-x2) + abs(y1-y2)
  • 8方向(含对角线)→ 用对角距离:max(abs(x1-x2), abs(y1-y2))(更准且快)
  • 不建议直接用欧氏距离平方(会失去可容许性),若要用请开根号并确保浮点精度可控

完整可运行示例(控制台版)

以下代码支持 2D 网格(int 类型障碍物标记),输出最短路径坐标序列:

立即学习C++免费学习笔记(深入)”;

摄图AI
摄图AI

摄图网旗下AI视觉创作平台

下载

#include 
#include 
#include 
#include 
#include 
#include 
#include 

struct Point { int x, y; bool operator==(const Point& o) const { return x == o.x && y == o.y; } };

// 哈希特化,用于 unordered_set/map namespace std { template<> struct hash { size_t operator()(const Point& p) const { return hash{}(p.x) ^ (hash{}(p.y) << 1); } }; }

// A* 节点(优先队列元素) struct Node { Point pos; float f, g; bool operator>(const Node& rhs) const { return f > rhs.f; } };

std::vector astar(const std::vector>& grid, Point start, Point end) { if (grid.empty() || grid[0].empty()) return {};

int rows = grid.size(), cols = grid[0].size();
auto in_bounds = [&](int x, int y) {
    return x youjiankuohaophpcn= 0 && x zuojiankuohaophpcn rows && y youjiankuohaophpcn= 0 && y zuojiankuohaophpcn cols;
};
auto is_walkable = [&](int x, int y) {
    return in_bounds(x, y) && grid[x][y] == 0; // 0=空地,1=障碍
};

// 启发式:对角距离(8向)
auto heuristic = [&](Point a, Point b) -youjiankuohaophpcn float {
    int dx = abs(a.x - b.x), dy = abs(a.y - b.y);
    return std::max(dx, dy) + (std::sqrt(2.0f) - 1.0f) * std::min(dx, dy);
};

std::priority_queuezuojiankuohaophpcnNode, std::vectorzuojiankuohaophpcnNodeyoujiankuohaophpcn, std::greaterzuojiankuohaophpcnNodeyoujiankuohaophpcnyoujiankuohaophpcn open;
std::unordered_setzuojiankuohaophpcnPointyoujiankuohaophpcn closed;
std::unordered_mapzuojiankuohaophpcnPoint, Pointyoujiankuohaophpcn came_from;
std::unordered_mapzuojiankuohaophpcnPoint, floatyoujiankuohaophpcn g_score;

open.push({start, heuristic(start, end), 0});
g_score[start] = 0;

const std::vectorzuojiankuohaophpcnstd::pairzuojiankuohaophpcnint,intyoujiankuohaophpcnyoujiankuohaophpcn dirs = {
    {-1,0},{1,0},{0,-1},{0,1}, // 上下左右
    {-1,-1},{-1,1},{1,-1},{1,1} // 对角(可选,注释掉即4向)
};

while (!open.empty()) {
    Node curr = open.top(); open.pop();
    if (curr.pos == end) break;
    if (closed.count(curr.pos)) continue;
    closed.insert(curr.pos);

    for (auto [dx, dy] : dirs) {
        Point next{curr.pos.x + dx, curr.pos.y + dy};
        if (!is_walkable(next.x, next.y)) continue;

        float move_cost = (dx == 0 || dy == 0) ? 1.0f : std::sqrt(2.0f);
        float tentative_g = g_score[curr.pos] + move_cost;

        if (!g_score.count(next) || tentative_g zuojiankuohaophpcn g_score[next]) {
            came_from[next] = curr.pos;
            g_score[next] = tentative_g;
            float f = tentative_g + heuristic(next, end);
            open.push({next, f, tentative_g});
        }
    }
}

// 回溯路径
std::vectorzuojiankuohaophpcnPointyoujiankuohaophpcn path;
for (Point curr = end; curr != start && came_from.count(curr); curr = came_from[curr]) {
    path.push_back(curr);
}
if (!path.empty() && path.back() != start) path.push_back(start);
std::reverse(path.begin(), path.end());
return path;

}

// 示例用法 int main() { // 0=可通过,1=墙 std::vector<:vector>> map = { {0,0,0,0,1}, {0,1,0,0,0}, {0,1,0,1,0}, {0,0,0,1,0}, {1,0,0,0,0} };

auto path = astar(map, {0,0}, {4,4});
std::cout zuojiankuohaophpcnzuojiankuohaophpcn "Path: ";
for (auto p : path) std::cout zuojiankuohaophpcnzuojiankuohaophpcn "(" zuojiankuohaophpcnzuojiankuohaophpcn p.x zuojiankuohaophpcnzuojiankuohaophpcn "," zuojiankuohaophpcnzuojiankuohaophpcn p.y zuojiankuohaophpcnzuojiankuohaophpcn ") ";
std::cout zuojiankuohaophpcnzuojiankuohaophpcn "\n";

}

集成到游戏项目的建议

  • Point换成你引擎的向量类型(如sf::Vector2iglm::ivec2),重载==hash
  • grid参数改为接口抽象(如auto getCell(x,y) -> CellType),支持动态地形或NavMesh采样
  • 加早停机制:设置最大搜索节点数(防卡死)或时间片(如每帧只算50个节点)
  • 路径平滑:对返回的折线路径做直线检测+跳点(JPS)或贝塞尔插值,提升视觉自然度

基本上就这些。A*本身不复杂,但细节(比如启发式选择、移动代价建模、内存管理)容易忽略,影响性能和路径质量。实际项目中常配合路径缓存、分层寻路(Hierarchical A*)或Flow Field做大规模单位调度——那是进阶方向了。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

311

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

511

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

46

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

179

2025.08.29

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

529

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

2

2025.12.22

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

980

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

39

2025.10.17

笔记本电脑卡反应很慢处理方法汇总
笔记本电脑卡反应很慢处理方法汇总

本专题整合了笔记本电脑卡反应慢解决方法,阅读专题下面的文章了解更多详细内容。

1

2025.12.25

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++教程
C++教程

共115课时 | 9.9万人学习

手把手实现数据传输编码
手把手实现数据传输编码

共1课时 | 700人学习

c语言项目php解释器源码分析探索
c语言项目php解释器源码分析探索

共7课时 | 0.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号