A星算法笔记

A星算法笔记

参考:https://blog.csdn.net/hitwhylz/article/details/23089415

[update]我新增了一篇文章,讲述了如何用A星算法实现一个自动吃食物的贪吃蛇小游戏

https://www.cnblogs.com/studentWangqy/p/18093364

原理

1.heuristic 启发式

F=G+H

G: distance between start and current node

H: distance between goal and current node

g(n)来表示从起点到任意节点n的路径花费

h(n)表示从节点n到目标节点路径花费的估计值(启发值)。

2.关于代价为啥要乘以10或14

从起始点水平/垂直地步进一格与斜对角步进一格,两者的cost是不同的

一般而言会认为斜对角的步进cost大于水平/垂直步进一格但是小于两格。

比如我们如果认为 水平/垂直方向步进一格的代价是10,那么就可以认为斜对角步进一格的代价是14

(但是如果移动方式不允许斜方向移动,例如贪吃蛇,那么就不必给移动的Manhattan距离乘以10或者14了)

3.Manhattan 距离:

曼哈顿距离(Manhattan distance)

对于方形网格,标准的启发式函数就是曼哈顿距离。

考虑一下你的代价函数并确定从一个位置移动到相邻位置的最小代价D。

在简单的情况下,你可以将D设为1。

在一个可以向4个方向移动的方向网格中,启发式函数是曼哈顿距离的D倍:

function Manhattan(node, goal, D) {

var dx = abs(node.x - goal.x);

var dy = abs(node.y - goal.y);

return D * (dx + dy);

}

可以看到曼哈顿距离就是x,y坐标的距离绝对值乘以一个考量值D

在示例中我们移动一格的G值为10,那么这里的D就是10,这么做的目的是为了将G和H的单位统一。

基本数据结构

1.全局数组:

open list

close list

start

goal

2.局部变量

current node

neibor node

3.结构体

struct node{

int F;

int G;

int H;

node* parent

};

伪码

初始化start, goal

把start加入open list

FOR open list

选择 F 值最小的 ( 方格 ) 节点 current

把它从 open list 里取出,放到 close list 中。

for 检查所有与 current 相邻的方格 neibor

IF 方格neibor不在open lsit 中,则把它加入到 open list 中。

把current设置为neibor的父亲。

计算neibor 的 F G H

ELSE IF neibor已经在 open list 中

则比较 neibor.G 和 G1 = current.G + Manhatan(current,neibor)

IF G1 > G 这条路径是否更优,也就是说经由当前方格 ( 我们选中的方格 ) 到达那个方格是否具有更小的 G 值。

则neibor.parent=current

重新计算neibor的 F 值和 G 值。

ELSE

不做任何操作。

ELSE IF 是 close list 中或是不可走 (unwalkable) 的方格

忽略

//TODO

回溯及打印

源码

完整源码

效果图