C++如何实现一个简单的A*寻路算法_C++游戏AI开发中的路径规划实战


A*算法通过评估函数f=g+h结合Dijkstra的完备性和贪心搜索的高效性,在二维网格中寻最优路径;使用优先队列扩展节点,曼哈顿距离作启发函数,记录g、h、f值及父节点回溯路径,最终实现从起点到终点的完整路径规划。

在C++游戏AI开发中,A*(A星)寻路算法是路径规划的核心技术之一。它结合了Dijkstra算法的完备性和贪心搜索的高效性,通过评估函数快速找到从起点到终点的最优路径。下面用简洁的方式实现一个基础但可用的A*算法,适用于二维网格地图。

1. 定义地图与节点结构

假设地图是一个二维网格,0表示可通过,1表示障碍物。每个节点记录坐标、代价信息以及父节点用于回溯路径。

#include 
#include 
#include 
#include 

struct Node { int x, y; float g, h; // g: 实际代价,h: 启发值 float f() const { return g + h; } Node* parent;

Node(int x, int y) : x(x), y(y), g(0), h(0), parent(nullptr) {}

bool operatorzuojiankuohaophpcn(const Node& other) const {
    return f() youjiankuohaophpcn other.f(); // 优先队列需要最小堆
}

};

2. 启发函数与邻居生成

使用曼哈顿距离作为启发函数,适合四方向移动。若支持八方向,可改用对角线距离或欧几里得距离。

float heuristic(int x1, int y1, int x2, int y2) {
    return abs(x1 - x2) + abs(y1 - y2); // 曼哈顿距离
}

std::vector> getNeighbors(int x, int y) { return {{x+1,y}, {x-1,y}, {x,y+1}, {x,y-1}}; // 若允许斜向移动,可加入 {x+1,y+1}, {x+1,y-1} 等 }

3. A* 核心算法实现

使用优先队列管理待处理节点,集合记录已访问位置,避免重复扩展。

std::vector aStar(const std::vector>& grid,
                           Node* start, Node* end) {
    int rows = grid.size();
    int cols = grid[0].size();
auto isValid = [&](int x, int y) {
    return x youjiankuohaophpcn= 0 && x zuojiankuohaophpcn rows && y youjiankuohaophpcn= 0 && y zuojiankuohaophpcn cols && grid[x][y] == 0;
};

std::priority_queuezuojiankuohaophpcnNodeyoujiankuohaophpcn openList;
std::vectorzuojiankuohaophpcnstd::vectorzuojiankuohaophpcnboolyoujiankuohaophpcnyoujiankuohaophpcn closedList(rows, std::vectorzuojiankuohaophpcnboolyoujiankuohaophpcn(cols, false));
std::vectorzuojiankuohaophpcnstd::vectorzuojiankuohaophpcnNode*youjiankuohaophpcnyoujiankuohaophpcn nodeMap(rows, std::vectorzuojiankuohaophpcnNode*youjiankuohaophpcn(cols, nullptr));

for (int i = 0; i zuojiankuohaophpcn rows; ++i)
    for (int j = 0; j zuojiankuohaophpcn cols; ++j)
        if (grid[i][j] == 0)
            nodeMap[i][j] = new Node(i, j);

start = nodeMap[start-youjiankuohaophpcnx][start-youjiankuohaophpcny];
end = nodeMap[end-youjiankuohaophpcnx][end-youjiankuohaophpcny];
start-youjiankuohaophpcnh = heuristic(start-youjiankuohaophpcnx, start-youjiankuohaophpcny, end-youjiankuohaophpcnx, end-youjiankuohaophpcny);

openList.push(*start);

while (!openList.empty()) {
    Node current = openList.top(); openList.pop();

    if (closedList[current.x][current.y]) continue;
    closedList[current.x][current.y] = true;

    if (current.x == end-youjiankuohaophpcnx && current.y == end-youjiankuohaophpcny) {
        // 回溯路径
        std::vectorzuojiankuohaophpcnNode*youjiankuohaophpcn path;
        Node* p = end;
        while (p != nullptr) {
            path.push_back(p);
            p = p-youjiankuohaophpcnparent;
        }
        return path;
    }

    for (auto& [nx, ny] : getNeighbors(current.x, current.y)) {
        if (!isValid(nx, ny) || closedList[nx][ny]) continue;

        Node* neighbor = nodeMap[nx][ny];
        float tentativeG = current.g + 1; // 假设每步代价为1

        if (tentativeG zuojiankuohaophpcn neighbor-youjiankuohaophpcng || !closedList[nx][ny]) {
            neighbor-youjiankuohaophpcnparent = &const_castzuojiankuohaophpcnNode&youjiankuohaophpcn(current);
            neighbor-youjiankuohaophpcng = tentativeG;
            neighbor-youjiankuohaophpcnh = heuristic(nx, ny, end-youjiankuohaophpcnx, end-youjiankuohaophpcny);
            openList.push(*neighbor);
        }
    }
}

return {}; // 无路径

}

4. 使用示例与清理资源

演示如何调用并输出结果。注意实际项目中建议使用智能指针或对象池管理内存。

int main() {
    std::vector> grid = {
        {0, 0, 0, 1, 0},
        {0, 1, 0, 1, 0},
        {0, 1, 0, 0, 0},
        {0, 0, 0, 1, 0},
        {0, 0, 0, 0, 0}
    };
Node* start = new Node(0, 0);
Node* end = new Node(4, 4);

auto path = aStar(grid, start, end);

if (!path.empty()) {
    std::cout zuojiankuohaophpcnzuojiankuohaophpcn "Found path:\n";
    for (auto it = path.rbegin(); it != path.rend(); ++it) {
        std::cout zuojiankuohaophpcnzuojiankuohaophpcn "(" zuojiankuohaophpcnzuojiankuohaophpcn (*it)-youjiankuohaophpcnx zuojiankuohaophpcnzuojiankuohaophpcn "," zuojiankuohaophpcnzuojiankuohaophpcn (*it)-youjiankuohaophpcny zuojiankuohaophpcnzuojiankuohaophpcn ") ";
    }
    std::cout zuojiankuohaophpcnzuojiankuohaophpcn "\n";
} else {
    std::cout zuojiankuohaophpcnzuojiankuohaophpcn "No path found.\n";
}

// 简单释放(实际应遍历所有创建的节点)
for (auto& row : grid)
    for (auto val : row)
        if (val == 0) /* 伪代码 */ delete /* 对应节点 */;
delete start; delete end;

return 0;

}

基本上就这些。这个实现虽然简单,但展示了A*在C++中的核心逻辑:代价评估、优先扩展、路径回溯。在真实游戏中,你可以进一步优化数据结构(如使用索引代替指针)、支持动态障碍、多单位协同避让等。不复杂但容易忽略细节,比如防止重复入队和正确更新g值。掌握基础后,扩展性强。


# c++  # node  # ai  # ios  # stream  # 指针  # 数据结构  # 对象  # 算法  # 曼哈顿  # 最优  # 点到  # 欧几里得  # 是一个  # 你可以  # 遍历  # 适用于  # 可通过 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化76771 】 【 技术知识130152 】 【 IDC云计算60162 】 【 营销推广131313 】 【 AI优化88182 】 【 百度推广37138 】 【 网站推荐60173 】 【 精选阅读31334


相关推荐: Python集合操作技巧_高效去重解析【教程】  Win11怎么关闭OneDrive同步_Win11取消自动备份文件【教程】  如何在Golang中处理数据库事务错误_回滚和日志记录  Win11怎么激活Windows10_Win11激活Win10系统方法【步骤】  Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件  Win11如何设置开机问候语 Win11修改登录界面提示【技巧】  Win10怎么关闭自动更新错误弹窗_Win10策略屏蔽失败提示减少干扰【防护】  如何使用Golang recover捕获panic_防止程序崩溃并处理异常  如何外贸网站设计-能留住客户提升用户体验!  Go 中 defer 在 goroutine 内部不生效的原因与执行时机详解  如何使用Golang捕获并记录协程panic_保证主程序稳定运行  Win11怎么设置虚拟内存最佳大小_Windows11性能选项自定义分页文件  Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)  Golang如何避免指针逃逸_Golang逃逸分析与堆栈优化策略  PHP cURL GET请求:正确设置请求头与身份认证的完整教程  Mac的“调度中心”与“空间”怎么用_Mac多桌面高效管理【技巧】  Windows蓝屏错误0x0000001E怎么修复_KMODEEXCEPTIONNOTHANDLED排查  Linux怎么查找死循环进程_Linux系统负载分析与进程彻底结束【教程】  c++怎么操作redis数据库_c++ hiredis库连接与命令执行【实战】  C++中的协变与逆变是什么?C++函数指针与返回类型详解【类型系统】  Win11如何设置系统声音_Win11系统声音调整教程【攻略】  如何使用Golang实现函数指针_函数变量与回调示例  ACF 教程:正确更新嵌套在多层 Group 字段内的子字段  如何使用Golang管理模块版本_Golanggo mod tidy与升级方法  php查询数据怎么导出csv_查询结果转csv文件保存【操作】  Win10怎样设置闹钟贪睡时间 Win10闹钟贪睡时长设置【步骤】  SAX解析器是什么,它与DOM在处理大型XML文件时有何不同?  Win11怎么更改任务栏位置_修改注册表将Win11任务栏置顶【教程】  Win11怎么关闭自动调节亮度 Win11禁用内容自适应亮度【设置】  php8.4如何配置ssl证书_php8.4https访问配置指南【教程】  为什么Go需要go mod文件_Go go mod文件作用说明  Win11任务栏怎么调到左边_Win11开始菜单居左设置教程【步骤】  PythonPandas数据分析项目教程_时间序列透视表应用  Win11怎么关闭通知中心_Windows11系统通知与专注助手设置  如何在 Laravel 中通过嵌套关联关系进行 orderBy 排序  php删除数据怎么软删除_添加is_del字段标记删除【技巧】  c++ namespace命名空间用法_c++避免命名冲突  Win10文件历史记录怎么用 Win10开启自动备份文件教程【防丢】  为什么本地php环境运行php脚本卡顿_php执行效率优化方法与设置【说明】  Win11怎么设置开机密码_Windows11账户登录选项PIN码  Win11怎么关闭自动更新 Win11永久关闭系统更新的有效方法【技巧】  如何优化Golang程序CPU性能_Golang CPU密集型任务优化方法  如何使用Golang包导出规则_控制函数和变量可见性  Win11怎么开启远程桌面连接_Windows11系统属性远程设置  Win11怎么设置任务栏大小_Windows11注册表修改TaskbarSi值  PythonGIL机制理解_多线程限制解析【教程】  c++怎么设置线程优先级与cpu亲和性_c++ 多核处理器性能绑定【指南】  本地php环境出现502错误_nginx或apache502badgateway解决技巧【解答】  mac怎么打开终端_MAC终端Terminal使用入门与常用命令【教程】  Windows10如何查看保存的WiFi密码_Win10命令行netsh wlan查询 

 2025-12-05

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

致胜网络推广营销网


致胜网络推广营销网

致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 915688610

 17370845950

 915688610@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.