A*寻路算法

算法流程说明:

说明:起始节点记作S,目标节点记作E,对于任意节点P,从S到当前节点P的总移动消耗记作GP,节点P到目标E的曼哈顿距离记作HP,从节点P到相邻节点N的移动消耗记作DPN,用于优先级排序的值F(N)记作FP

  1. 选择起始节点S和目标节点E,将(S,0)(节点,节点F(N)值)放入openList,openList是一个优先队列,节点F(N)值越小,优先级越高。
  2. 判断openList是否为空,若为空,则搜索失败,目标节点不可达;否则,取出openList中优先级最高的节点P;
  3. 遍历P的上下左右四个相邻接点N1-N4,对每个节点N,如果N已经在closeList中,忽略;否则有两种情况;
    • 如果N不在openList中,令GN=GP+DPN,计算N到E的曼哈顿距离HN,令FN=GN+HN,令N的父节点为P,将(N,FN)放入openList;
    • 如果N已经在openList中,计算GN1= GP+DPN,如果GN1小于GN,那么用新的GN1替换GN,重新计算FN,用新的(N,FN)替换openList中旧的(N,FN),令N的父节点为P;如果GN1不小于GN,不作处理。
  4. 将节点P放入closeList中。判断节点P是不是目标节点E,如果是,搜索成功,获取节点P的父节点,并递归这一过程(继续获得父节点的父节点),直至找到初始节点S,从而获得从P到S的一条路径;否则,重复步骤2;

效果如下:

主要代码

// 寻路
function findWay(mapArr, oStart, oEnd) {
let curPoint = null,
bFind = true; // 是否检索
curPointArr = []; // 当前指针
let n = 0; let startX = oStart.x,
startY = oStart.y,
endX = oEnd.x,
endY = oEnd.y;
curPoint = oStart;
//起始和结束相邻,直接结束
if ((Math.abs(startX - endY) == 1 && Math.abs(startY - endY) == 1) || (Math.abs(startX - endX) == 0 && Math.abs(startY - endY) == 1) || (Math.abs(startX - endX) == 1 && Math.abs(startY - endY) == 0)) {
bFind = false;
setTimeout(function () {
alert('起始和结束位置相邻');
}, 300)
} // 递归寻路
while (bFind) {
opens = getRound(curPoint);
if (opens.length == 0) {
alert('无路可走');
return;
}
// 选取最近的路线
opens.sort(function (a, b) {
return a.num - b.num;
});
curPoint = opens.shift();
curPointArr.push(curPoint);
// 关闭其他路线
closes = closes.concat(opens);
closes.push(curPoint);
opens = [];
// 结束
if (curPoint == oEnd) {
bFind = false;
}
}
if (!bFind) {
showLine()
}
} // 获取打开的opensList
function getRound(curPoint) {
let opens = [];
let curX=curPoint.x,
curY=curPoint.y;
for (let i = 0; i < mapArr.length; i++) {
for (let j = 0; j < mapArr[0].length; j++) {
// 选取可以走的可能
//走斜线
if ((Math.abs(curX - i) == 0 && Math.abs(curY - j) == 1) || (Math.abs(curX - i) == 1 && Math.abs(curY - j) == 0) || (Math.abs(curX - i) == 1 && Math.abs(curY - j) == 1)) {
if (closes.indexOf(mapArr[i][j]) == -1 && mapArr[i][j].val != 3 && mapArr[i][j] != oStart) {
if (curX<mapArr.length-1 && mapArr[curX + 1][curY].val == 3) {
if (j<mapArr[0].length-1 && mapArr[curX][curY+1].val == 3 && curX + 1 == i && curY + 1 == j) {
continue;
}else if(curY>0 && mapArr[curX][curY-1].val==3 && curX + 1 == i && curY - 1 == j) {
continue;
}
}else if (curX>0 && mapArr[curX - 1][curY].val == 3) {
if (curY<mapArr[0].length-1 && mapArr[curX][curY+1].val == 3 && curX - 1 == i && curY + 1 == j) {
continue;
}else if(curY>0 && mapArr[curX][curY-1].val==3 && curX - 1 == i && curY - 1 == j) {
continue;
}
}
mapArr[i][j].num = h(mapArr[i][j]);
opens.push(mapArr[i][j]);
}
}
}
}
return opens
}

源代码下载:https://github.com/LianJianQiang/algorithm.git

参考文章:

JS算法之A*寻路

js算法之寻路的更多相关文章

  1. js算法集合(一) 水仙花数 及拓展(自幂数的判断)

    js算法集合(一) ★ 最近有些朋友跟我说对js中的一些算法感到很迷惑,知道这个算法到底是怎么回事,但是就是不会用代码把它写出来,这里我跟大家分享一下做水仙花数的算法的思路,并对其扩展到自幂数的算法, ...

  2. js算法集合(二) javascript实现斐波那契数列 (兔子数列)

    js算法集合(二)  斐波那契数列 ★ 上一次我跟大家分享一下做水仙花数的算法的思路,并对其扩展到自幂数的算法,这次,我们来对斐波那契数列进行研究,来加深对循环的理解.     Javascript实 ...

  3. js算法初窥03(简单搜索及去重算法)

    前面我们了解了一些常用的排序算法,那么这篇文章我们来看看搜索算法的一些简单实现,我们先来介绍一个我们在实际工作中一定用到过的搜索算法--顺序搜索. 1.顺序搜索 其实顺序搜索十分简单,我们还是以第一篇 ...

  4. JS算法练习四

    JS算法练习 1.将使用空格分隔单词使用驼峰命名连接起来: var str="HELLO world welcome to my hometown"; /*--先输入一个有空格分隔 ...

  5. JS算法练习三

    JS算法练习 1.生成一个长度为10的随机数组,使用冒泡法给数组排序 var arr=new Array(10); for (var i = 0; i <arr.length ; i++) { ...

  6. JS算法练习二

    JS算法练习 1.生成4位的随机验证码,可取大小写字母和数字 ? var validateCode = "", /*--存放生成好的验证码字符串--*/ count = 0; /* ...

  7. JS算法练习一

    JS算法练习 1.随机生成一个五位以内的数,然后输出该数共有多少位,每位分别是什么? ①.数组添加元素的方式得到位数(数组长度)与值(数组元素) ①.数组添加元素的方式得到位数(数组长度)与值(数组元 ...

  8. js算法初窥05(算法模式02-动态规划与贪心算法)

    在前面的文章中(js算法初窥02(排序算法02-归并.快速以及堆排)我们学习了如何用分治法来实现归并排序,那么动态规划跟分治法有点类似,但是分治法是把问题分解成互相独立的子问题,最后组合它们的结果,而 ...

  9. js算法初窥03(搜索及去重算法)

    前面我们了解了一些常用的排序算法,那么这篇文章我们来看看搜索算法的一些简单实现,我们先来介绍一个我们在实际工作中一定用到过的搜索算法——顺序搜索. 1.顺序搜索 其实顺序搜索十分简单,我们还是以第一篇 ...

随机推荐

  1. pytong下安装安装SK-Learn

    安装SK-Learn需要依赖的Python安装包有: Python (>= 2.6), NumPy (>= 1.3), SciPy (>= 0.7), 下载python的各种包的地址 ...

  2. scrapy的使用--Rcrapy-Redis

    Scrapy-Redis分布式爬虫组件 Scrapy是一个框架,他本身是不支持分布式的.如果我们想要做分布式的爬虫.就需要借助一个组件叫做Scrapy-Redis.这个组件正式利用了Redis可以分布 ...

  3. Winform 获取桌面设备上下文

    //获得桌面设备上下文 us(Graphics g = Graphics.FromHwnd(IntPtr.Zero)) { g.DrawLine(Pens.Red, , , , ); }

  4. 9款很棒的网页绘制图表JavaScript框架脚本

    推荐9款很棒的可在网页中绘制图表的JavaScript脚本,这些有趣的JS脚本可以帮助你快速方便的绘制图表(线.面.饼.条…),其中包括jQuery.MooTools.Prototype和一些其它的J ...

  5. logback日志文件的使用

    1.引入Jar包,Maven pom.xml <!-- Logging with SLF4J & LogBack --> <dependency> <groupI ...

  6. JS对象 向上取整ceil() ceil() 方法可对一个数进行向上取整。 语法: Math.ceil(x) 注意:它返回的是大于或等于x,并且与x最接近的整数。

    向上取整ceil() ceil() 方法可对一个数进行向上取整. 语法: Math.ceil(x) 参数说明: 注意:它返回的是大于或等于x,并且与x最接近的整数. 我们将把 ceil() 方法运用到 ...

  7. Linux queue.h之TAILQ队列分析

    转自 这两天想看看memcached的实现,所以先学习了libevent,使用起来还是比较简单的,其实是对select/poll/kqueue等的封装,学习libevent过程中又遇到了linux下队 ...

  8. Centos 6.5 python版本升级到2.7.8

    Centos6.5默认的 python版本是2.6 为了使用aliyuncli工具,直接用pip安装aliyuncli提示错误. 所以决定升级下python版本,但是yum依赖于python2.6,升 ...

  9. window 系统上传文件到linux 系统出现dos 格式换行符

    Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行,所以为了避免这种情况的发生,我们可以 ...

  10. Appium 微信 webview 的自动化技术

    Appium 微信 webview 的自动化技术   最近好多人问微信webview自动化的事情, 碰巧我也在追微信webview的自动化和性能分析方法. 先发出来一点我的进展给大家参考下. 此方法用 ...