✨ 简介 :A*算法是人工智能、游戏开发、机器人路径规划中最经典的启发式寻路算法。相比于BFS盲目搜索,A*通过启发函数定向搜索,效率更高、路径最优。本文基于C语言实现4方向A*寻路,附带完整源码、逐行解析、案例演示、优缺点总结,零基础也能看懂!
@TOC(文章目录)
一、A*算法核心介绍
1.1 算法定位
A*(A-Star)是一种基于启发式搜索的最优路径算法,结合了Dijkstra算法的稳定性和贪心算法的高效性:
-
BFS:盲目遍历所有节点,无方向,效率低
-
贪心算法:只看终点距离,容易绕路,无法保证最优解
-
A*算法 :综合实际代价+预估代价,高效且保证最短路径
1.2 核心公式
A*算法通过代价函数 F = G + H 筛选最优节点
-
G(g) :实际代价,从起点移动到当前节点的真实步数
-
H(h) :启发预估代价,当前节点到终点的预估距离(本文使用曼哈顿距离)
-
F(f):综合代价,F值越小,节点优先级越高,优先遍历
曼哈顿距离公式(4方向移动专用):
H = \|x_1 - x_2\| + \|y_1 - y_2\|
二、算法执行流程
-
初始化地图、节点信息、开启列表、关闭列表;
-
将起点加入开启列表,初始化起点代价G=0;
-
循环遍历开启列表,选出F值最小的节点作为当前节点;
-
若当前节点是终点,回溯父节点,生成最优路径;
-
若开启列表为空,判定无可行路径;
-
遍历当前节点上下左右四个方向邻节点,更新代价与父节点信息;
-
将当前节点移入关闭列表,重复循环直至找到终点。
三、测试地图案例
本文采用 5×5网格地图,0代表可通行区域,1代表障碍物
起点 :(0,0) 终点:(4,4)
地图布局:
行0: 0 0 0 0 0
行1: 0 1 0 1 0
行2: 0 0 0 1 0
行3: 0 1 1 1 0
行4: 0 0 0 0 0
障碍物坐标:(1,1)、(1,3)、(2,3)、(3,1)、(3,2)、(3,3)
四、完整可运行源码
代码纯C语言实现,无依赖库,支持任意尺寸网格地图,直接复制即可编译运行!
cpp
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
// 定义地图行列数
#define ROWS 5
#define COLS 5
// 全局地图:0可通行 1障碍物
int grid[ROWS][COLS] = {
{0, 0, 0, 0, 0},
{0, 1, 0, 1, 0},
{0, 0, 0, 1, 0},
{0, 1, 1, 1, 0},
{0, 0, 0, 0, 0}
};
// 节点结构体:存储每个网格的代价、父节点、状态
typedef struct {
int r, c; // 当前节点坐标
int g; // 起点到当前点实际代价
int h; // 当前点到终点预估代价
int parent_r, parent_c; // 父节点坐标(用于回溯路径)
bool in_open; // 是否在开启列表中
} Node;
/**
* @brief 曼哈顿距离启发函数
* @param r1,c1 当前节点坐标
* @param r2,c2 终点坐标
* @return 预估距离
*/
int heuristic(int r1, int c1, int r2, int c2) {
return abs(r1 - r2) + abs(c1 - c2);
}
/**
* @brief A*寻路核心函数
* @param sr,sc 起点坐标
* @param er,ec 终点坐标
*/
void astar(int sr, int sc, int er, int ec) {
Node nodes[ROWS][COLS];
bool closed[ROWS][COLS] = {false}; // 关闭列表:已遍历节点
// 1. 初始化所有节点信息
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
nodes[i][j].r = i;
nodes[i][j].c = j;
nodes[i][j].g = INT_MAX; // 初始实际代价无穷大
nodes[i][j].h = heuristic(i, j, er, ec); // 初始化启发代价
nodes[i][j].parent_r = -1;
nodes[i][j].parent_c = -1;
nodes[i][j].in_open = false;
}
}
// 初始化起点
nodes[sr][sc].g = 0;
nodes[sr][sc].in_open = true;
// 上下左右4个移动方向
int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
// A*主循环
while (1) {
// 2. 遍历开启列表,找到F值最小的节点
int minF = INT_MAX;
int cr = -1, cc = -1;
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
if (nodes[i][j].in_open && !closed[i][j]) {
int f = nodes[i][j].g + nodes[i][j].h;
if (f < minF) {
minF = f;
cr = i;
cc = j;
}
}
}
}
// 开启列表为空,无路径
if (cr == -1) {
printf("无可行路径!\n");
return;
}
// 3. 到达终点,回溯输出路径
if (cr == er && cc == ec) {
int path_r[100], path_c[100];
int len = 0;
int r = er, c = ec;
// 从终点反向回溯到起点
while (r != -1) {
path_r[len] = r;
path_c[len] = c;
len++;
int pr = nodes[r][c].parent_r;
int pc = nodes[r][c].parent_c;
r = pr;
c = pc;
}
// 正向输出路径
printf("✅ A*最优寻路路径:\n");
for (int i = len - 1; i >= 0; i--) {
printf("(%d,%d) ", path_r[i], path_c[i]);
}
printf("\n📏 路径总长度:%d\n", len);
return;
}
// 当前节点加入关闭列表,不再重复遍历
closed[cr][cc] = true;
nodes[cr][cc].in_open = false;
// 4. 遍历四个方向邻节点,更新代价
for (int d = 0; d < 4; d++) {
int nr = cr + dirs[d][0];
int nc = cc + dirs[d][1];
// 边界判断、障碍物判断、已关闭节点判断
if (nr < 0 || nr >= ROWS || nc < 0 || nc >= COLS) continue;
if (grid[nr][nc] == 1 || closed[nr][nc]) continue;
// 计算新的实际代价
int ng = nodes[cr][cc].g + 1;
// 新路径更优则更新节点信息
if (ng < nodes[nr][nc].g) {
nodes[nr][nc].g = ng;
nodes[nr][nc].parent_r = cr;
nodes[nr][nc].parent_c = cc;
nodes[nr][nc].in_open = true;
}
}
}
}
int main(void) {
// 起点(0,0) 终点(4,4)
astar(0, 0, 4, 4);
return 0;
}
五、代码逐模块解析
5.1 结构体设计
自定义Node结构体,封装每个网格节点的所有属性,统一管理代价、坐标、父节点、遍历状态,逻辑清晰,便于维护。
5.2 启发函数设计
采用曼哈顿距离,适配上下左右4方向移动场景,计算简单、效率高,是网格寻路的最优启发函数。
5.3 核心遍历逻辑
每次迭代筛选F值最小的节点优先扩展,保证搜索方向始终朝向终点,避免无效遍历,兼顾搜索效率与路径最优性。
5.4 路径回溯机制
到达终点后,通过父节点坐标反向回溯整条路径,再反转输出正向行走路线,完美还原完整寻路轨迹。
六、程序运行结果
编译运行代码后,输出最优路径如下:
cpp
✅ A*最优寻路路径:
(0,0) (0,1) (0,2) (0,3) (0,4) (1,4) (2,4) (3,4) (4,4)
📏 路径总长度:9
结果分析:算法成功避开所有障碍物,规划出最短可行路径,无绕路、无死角,完美验证A*算法最优性。
七、算法优缺点总结
✅ 优点
-
具备启发搜索能力,相比BFS效率大幅提升
-
在启发函数合理的前提下,一定能找到全局最优路径
-
逻辑清晰、实现简单,适配网格地图场景
-
广泛应用于游戏寻路、机器人导航、自动驾驶路径规划
❌ 缺点
-
本文采用暴力遍历查找最小F值,大数据场景效率较低(可优化为最小堆)
-
仅支持4方向移动,无法适配斜向移动场景
-
依赖启发函数设计,H值不合理会导致丢失最优解
八、优化拓展方向
-
最小堆优化:替换暴力遍历,将时间复杂度大幅降低;
-
8方向移动:增加对角线移动方向,适配更多场景;
-
可视化输出:打印带路径标记的地图,直观展示寻路轨迹;
-
动态地图:支持动态修改障碍物,实现实时寻路。
九、总结
A*算法是路径规划领域的入门必学算法,相比传统暴力搜索,通过F=G+H的启发策略,实现了高效且精准的最优路径搜索。本文的C语言实现代码简洁、注释详细、适配新手,可直接用于课程作业、算法入门学习与项目二次开发。