算法核心


A*估值算法

寻路估值算法有非常多:常用的有广度优先算法,深度优先算法,哈夫曼树等等,游戏中用的比较多的如:A*估值

算法描述

  • 对起点与终点进行横纵坐标的运算

代码实现

  • start: 起点坐标(point)

  • end: 终点坐标(point)

  • Math.abs(start.getX() - end.getX()) + Math.abs(start.getY() - end.getY());

算法逻辑


  • 寻路过程中检索关联点(路径点)

  • 对关联点分类(分为已经关联与未关联)

  • 对未关联的点用寻路算法对其进行一次标识(每个点需要3种标识)

  • 对比关联点的标识找出下一步的最优路径

  • 循环上几步的操作,直到终点

算法实现


  • 定义一个容器,在js中使用数组[ ],为了更好描述算法,在Array中实现几个方法

判断容器中是否存在该点:

  1. // 根据对象判断
  2. Array.prototype.isExistByValue = function(value) {
  3. for (var i = 0; i < this.length; i++) {
  4. if (value.getX() == this[i].getX() && value.getY() == this[i].getY()) {
  5. return this[i];// 对象总是为真
  6. }
  7. }
  8. return false;
  9. }
  10. // 根据对象中的属性值判断
  11. Array.prototype.isExistByProperty = function(x, y) {
  12. for (var i = 0; i < this.length; i++) {
  13. if (x == this[i].getX() && y == this[i].getY()) {
  14. return true;
  15. }
  16. }
  17. return false;
  18. }

移除一个点:

  1. // 根据点的属性值移除点
  2. Array.prototype.removeValue = function(x, y) {
  3. for (var i = 0; i < this.length; i++) {
  4. if (x == this[i].getX() && y == this[i].getY()) {
  5. this.splice(i,1);
  6. }
  7. }
  8. }
  9. // 根据对象删除点
  10. Array.prototype.remove = function(value) {
  11. for (var i = 0; i < this.length; i++) {
  12. if (value == this[i]) {
  13. this.splice(i,1);
  14. }
  15. }
  16. }

添加一个点:

  1. // 根据点的坐标属性添加点到容器中
  2. Array.prototype.add = function(x, y) {
  3. var v = new pathUtils.locationPoint(x,y);
  4. this.push(v);
  5. }

根据点对象从容器中拿取该点,没有return null:

  1. Array.prototype.getValue = function(value) {
  2. for (var i = 0; i < this.length; i++) {
  3. if (value.getX() == this[i].getX() && value.getY() == this[i].getY()) {
  4. return this[i];
  5. }
  6. }
  7. return null;
  8. }

根据点的某一属性取出该点:

  1. // 把最小F值的point找出来
  2. Array.prototype.getValueByProperty = function() {
  3. var minF = this[0].getF();
  4. for (var i = 0; i < this.length; i++) {
  5. if (minF > this[i].getF()) {
  6. minF = this[i].getF();
  7. }
  8. }
  9. for (var i = 0; i < this.length; i++) {
  10. if (minF == this[i].getF()) {
  11. return this[i];
  12. }
  13. }
  14. return this[0];
  15. }
  • 寻路逻辑:
  1. pathUtils.pathLogic = function(start, end, obstacArr) {
  2. this.openList = [];
  3. this.closeList = [];
  4. this.openList.push(start);
  5. while(this.openList.length != 0){
  6. var smallF = this.openList.getValueByProperty();
  7. this.openList.remove(smallF);
  8. this.closeList.push(smallF);
  9. var suround = this.getSurroundPath(smallF,obstacArr);
  10. for (var i = 0; i < suround.length; i++) {
  11. var tempObj = this.openList.isExistByValue(suround[i]);
  12. if (tempObj) {
  13. this.foundInOpenList(smallF,tempObj);
  14. }else{
  15. this.notFoundInOpenList(smallF,end,suround[i]);
  16. }
  17. }
  18. if (this.openList.getValue(end) != null) {
  19. this.closeList.push(end);
  20. return this.closeList;
  21. }
  22. }
  23. }
  24. pathUtils.calcG = function(start, point) {
  25. var G = (Math.abs(point.getX() - start.getX()) + Math.abs(point.getY() - start.getY())) == 1 ? utils.Const.PATH_HORIZONTAL_VERTICAL : utils.Const.PATH_OBLIQUITY;
  26. return (G + point.getParentPoint().getG());
  27. }
  28. pathUtils.calcH = function(end, point) {
  29. var h = Math.abs(point.getX() - end.getX()) + Math.abs(point.getY() - end.getY());
  30. return h * utils.Const.PATH_HORIZONTAL_VERTICAL;
  31. }
  32. pathUtils.getSurroundPath = function(point, obstacArr) {
  33. var surroundArr = [];
  34. for (var i = point.getX() - 1; i <= point.getX() + 1; i++) {
  35. for (var j = point.getY() -1; j <= point.getY() + 1; j++) {
  36. if (this.closeList.isExistByProperty(i,j)) continue;
  37. if (obstacArr && obstacArr.length && obstacArr.isExistByProperty(i,j)) continue;
  38. surroundArr.add(i,j);
  39. }
  40. }
  41. return surroundArr;
  42. }
  43. pathUtils.foundInOpenList = function(tempPoint, point) {
  44. var G = this.calcG(tempPoint,point);
  45. if (G < point.getG()) {
  46. point.setParentPoint(tempPoint);
  47. point.setG(G);
  48. point.calcF();
  49. }
  50. }
  51. pathUtils.notFoundInOpenList = function(tempPoint, end, point) {
  52. point.setParentPoint(tempPoint);
  53. point.setG(this.calcG(tempPoint,point));
  54. point.setH(this.calcH(end,point));
  55. point.calcF();
  56. this.openList.push(point);
  57. }

算法细节


需要注意的几点

  • 点对象中标识G的计算

  • 点对象中标识H的计算

  • 点对象已经被关联过

  • 点对象未被关联过

要点突破

  • 当前起点与终点的parent是为null(没有父节点的概念)

  • G值计算:

    1. 相对于起点G值一直增大(横竖走一步消耗为10,斜向走一步消耗为14)

    2. G值有8个方向需要计算

    3. G值总是越靠近终点值越小

  • H值计算:

    1. 相对于起点H值一直减小(离终点近一步-10,离终点远一步+10)

    2. H值有4个方向需要计算

    3. H值相对于终点是不变的

  • 点已被关联过:

    1. 如果某个相邻方格已经在openList里了, 检查如果用新的路径 (就是经过最优点的路径) 到达它的话, G值是否会更低一些

    2. 如果新的G值更低, 那就把它的parent改为目前选中的方格, 然后重新计算它的 F 值和 G 值 (H 值不需要重新计算, 因为对于每个方块, H 值是不变的)

    3. 如果新的 G 值比较高, 就说明经过最优点再到达该相邻点不是一个明智的选择, 因为它需要更远的路, 这时我们什么也不做

  • 点未被关联过:

    1. 检查它所有相邻并且可以到达 (障碍物和closeList的方格都不考虑) 的方格. 如果这些方格还不在openList里的话, 将它们加入openList, 计算这些方格的 G, H 和 F 值各是多少, 并设置它们的parent为该最优点

算法总结


  • A*算法并非是寻路中最好的算法,但由于其实现简单所以在工程中大量使用

  • A*寻路整体不是非常难,只要注意细节就不会出现bug

JS - A*寻路的更多相关文章

  1. javascript的Astar版 寻路算法

    去年做一个模仿保卫萝卜的塔防游戏的时候,自己写的,游戏框架用的是coco2d-html5 实现原理可以参考 http://www.cnblogs.com/technology/archive/2011 ...

  2. js实现A*寻路算法

    这两天在做百度前端技术学院的题目,其中有涉及到寻路相关的,于是就找来相关博客进行阅读. 看了Create Chen写的理解A*寻路算法具体过程之后,我很快就理解A*算法的原理.不得不说作者写的很好,通 ...

  3. PathFinding.js 寻路类神器

    最近有打算写个迷宫玩玩,无意中发下了这个库,很强大!又是开源在github的,并且有一个相当酷的demo.这个库不仅支持浏览器端的运行,而且可以运行在node.js上.怎么用到服务器上这里就不涉及了, ...

  4. js算法之寻路

    A*寻路算法 算法流程说明: 说明:起始节点记作S,目标节点记作E,对于任意节点P,从S到当前节点P的总移动消耗记作GP,节点P到目标E的曼哈顿距离记作HP,从节点P到相邻节点N的移动消耗记作DPN, ...

  5. 【JS】 Javascript与BOM的互动 寻路

    JS BOM 之前提到过JS和DOM之间的互动方法.而BOM(Browser Object Module)是浏览器的对象模型,它也可以和JS进行互动.也就是说,JS还可以和浏览器进行互动.因为现代主流 ...

  6. 【JS】 Javascript与HTML DOM的互动 寻路

    JS HTML DOM DOM的全程是Document Object Module,即文档对象模型.一般来说,当一个页面被加载时,浏览器会在内部创建一个当前文档的DOM.就像用python的Etree ...

  7. JS算法之A*(A星)寻路算法

    今天写一个连连看的游戏的时候,接触到了一些寻路算法,我就大概讲讲其中的A*算法. 这个是我学习后的一点个人理解,有错误欢迎各位看官指正. 寻路模式主要有三种:广度游戏搜索.深度优先搜索和启发式搜索. ...

  8. JS中实现A*算法寻路

    <html><head><title>use A* to find path...</title></head><body style ...

  9. unity自带寻路Navmesh入门教程(一)

    说明:从今天开始,我阿赵打算写一些简单的教程,方便自己日后回顾,或者方便刚入门的朋友学习.水平有限请勿见怪.不过请尊重码字截图录屏的劳动,如需转载请先告诉我.谢谢! unity自从3.5版本之后,增加 ...

随机推荐

  1. ASP渲染下拉框使时间依次减少

    <%    x=year(now())    y=year(now())-1    Do While  y>2002%><li><a href="#201 ...

  2. ST 单元测试之maven安装

    junit是用于单元测试的jar包,可以直接下载然后粘贴至lib目录,maven是专门的包管理工具,所以尝试安装maven. 安装maven之前需要先安装好java以及eclipse,在相应的官网下载 ...

  3. Levenshtein distance 编辑距离

    编辑距离,又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符 实现方案: 1. 找出最长 ...

  4. html中submit和button的区别(总结) [ 转自欣步同学 ]

    html中submit和button的区别(总结) submit是button的一个特例,也是button的一种,它把提交这个动作自动集成了. 如果表单在点击提交按钮后需要用JS进行处理(包括输入验证 ...

  5. Mysql 保留最新的10条数据

    Mysql每天执行计划,保留最新的10条数据,其余的删除 1.Mysql 保留最新的10条数据 sql语句: DELETE tb FROM tbname AS tb,( SELECT id FROM ...

  6. Effective Modern C++ Item 37:确保std::thread在销毁时是unjoinable的

    下面这段代码,如果调用func,按照C++的标准,程序会被终止(std::terminate) void func() { std::thread t([] { std::chrono::micros ...

  7. django进阶-3

    先看效果图: 登陆admin后的界面: 查看作者: 当然你也可以定制admin, 使界面更牛逼 数据库表结构: app01/models.py from django.db import models ...

  8. Java中的常量治理

    版权声明:本文为博主原创文章,转载请注明出处,欢迎使劲喷 虽然推崇在java中使用枚举(可查看<Java中的枚举的治理>)来对数据字典及常量进行控制,但是有些时候,我们还是会觉得常量控制更 ...

  9. Spring Boot 整合 Mybatis 实现 Druid 多数据源详解

    摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! “清醒时做事,糊涂时跑步,大怒时睡觉,独处时思考” 本文提纲一.多数据源的应用场景二.运行 sp ...

  10. 用excel.php类库导出excel文件

    excel.php是个小型的php类库,可以满足基本的从数据库中取出数据然后导出xls格式的excel文件,代码如下: 1 class Excel { 2 public $filename = 'ex ...