Javascript版A*(a star)算法

本文介绍了一个使用 JavaScript 实现的 A* (A Star) 寻路算法示例。该算法通过构建地图和设置起点终点来寻找最优路径,并在 HTML 页面上直观展示寻路过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. <script type="text/javascript">
  2. var map = function(){
  3.     var owner = this;
  4.     //起点
  5.     this.startNode = [];
  6.     //map table
  7.     this.table = null;
  8.     //清除颜色
  9.     this.clearColor = function(){
  10.         var xl = this.length;
  11.         if(xl<1){
  12.             return;
  13.         }
  14.         var yl = this[0].length;
  15.         if(yl<1){
  16.             return;
  17.         }
  18.         var maptable = this.table;
  19.         maptable.style.display = 'none';
  20.         for(var i=0;i<xl;i++){
  21.             for(var n=0;n<yl;n++){
  22.                 maptable.rows[i].cells[n].style.background='';
  23.                 if(this[i][n]!=0){
  24.                     maptable.rows[i].cells[n].style.background='background';
  25.                 }
  26.             }
  27.         }
  28.         maptable.style.display = 'block';
  29.     }
  30.     //寻路
  31.     this.run = function(obj){
  32.         var x0=0,y0=0,x1=0,y1=0;
  33.         var _sn = this.startNode;
  34.         var _en = this.endNode;
  35.         if(_sn.length<1){
  36.             obj.style.background = 'red';
  37.             x0 = obj.parentNode.rowIndex;
  38.             y0 = obj.cellIndex;
  39.             this.startNode = [x0,y0];
  40.         }else{
  41.             this.clearColor();
  42.             obj.style.background = 'red';
  43.             x0 = _sn[0];
  44.             y0 = _sn[1];
  45.             x1 = obj.parentNode.rowIndex;
  46.             y1 = obj.cellIndex;
  47.             var path = this.getPath(x0,y0,x1,y1);
  48.             this.showPath(path);
  49.             this.startNode = [x1,y1];
  50.         }
  51.     }
  52.     //点击事件
  53.     this.click = function(event){
  54.         eventevent = event||window.event;
  55.         var obj = event.srcElement||event.target;
  56.         if(obj.tagName!='TD'){
  57.             return;
  58.         }
  59.         owner.run(obj);
  60.     }
  61.     //创建视图
  62.     this.setView = function(){
  63.         var xl = this.length;
  64.         if(xl<1){
  65.             return;
  66.         }
  67.         var yl = this[0].length;
  68.         if(yl<1){
  69.             return;
  70.         }
  71.         var trstr = '<tr>'+new Array(yl+1).join('<td></td>')+'</tr>';
  72.         var tbstr = '<table id="amap">'+new Array(xl+1).join(trstr)+'</table>';
  73.         document.write(tbstr);
  74.         var maptable = this.table = document.getElementById("amap");
  75.         for(var i=0;i<xl;i++){
  76.             for(var n=0;n<yl;n++){
  77.                 if(this[i][n]!=0){
  78.                     maptable.rows[i].cells[n].style.background='background';
  79.                 }
  80.             }
  81.         }
  82.         if(window.attachEvent){
  83.             this.table.attachEvent('onclick',this.click);
  84.         }else{
  85.             this.table.addEventListener('click',this.click,false);
  86.         }
  87.     }
  88.     //显示路径
  89.     this.showPath = function(path){
  90.         if(path!=undefined && path.length>0){
  91.             var maptable = this.table;
  92.             var pos = null;
  93.             var move = function(){
  94.                 if(path.length>0){
  95.                     pos = path.shift();
  96.                     maptable.rows[pos[0]].cells[pos[1]].style.background='red';
  97.                     window.setTimeout(arguments.callee,30);
  98.                 }
  99.             }
  100.             move();
  101.         }else{
  102.             document.title = 'Did not find the path!';
  103.         }
  104.     }
  105. }
  106. var Astar = function(map){
  107.     //dh20156;
  108.     this.map = map;
  109.     //已探索列表
  110.     this.chkList = [];
  111.     //开放对象列表
  112.     this.openList = [];
  113.     //取G值
  114.     this.getG = function(x0,y0,x1,y1){
  115.         if(Math.abs(x0-x1)==1 && Math.abs(y0-y1)==1){
  116.             return 14;
  117.         }else{
  118.             return 10;
  119.         }
  120.     }
  121.     //取H值Diagonal Shortcut
  122.     this.getH = function(x0,y0,x1,y1){
  123.         var xDistance = Math.abs(x0-x1);
  124.         var yDistance = Math.abs(y0-y1);
  125.         if(xDistance > yDistance){
  126.             return (14*yDistance + 10*(xDistance-yDistance));
  127.         }else{
  128.             return (14*xDistance + 10*(yDistance-xDistance));
  129.         }
  130.     }
  131.     //节点对象
  132.     this.point = function(_f,_g,_h,_x,_y,_p){
  133.         this.f = _f;
  134.         this.g = _g;
  135.         this.h = _h;
  136.         this.x = _x;
  137.         this.y = _y;
  138.         this.p = _p;
  139.     }
  140.     //获取检测子节点对象
  141.     this.setPoints = function(_node,x1,y1){
  142.         var map = this.map;
  143.         var x = _node.x;
  144.         var y = _node.y;
  145.         var g = _node.g;
  146.         var t = x-1;
  147.         var b = x+1;
  148.         var l = y-1;
  149.         var r = y+1;
  150.         var maxX = map.length;
  151.         var maxY = map[0].length;
  152.         if(t>=0 && l>=0 && map[t][l]==0 && map[t][y]==0 && map[x][l]==0) this.chkPoint(_node,x,y,g,t,l,x1,y1);//1
  153.         if(t>=0 && map[t][y]==0) this.chkPoint(_node,x,y,g,x-1,y,x1,y1);//2
  154.         if(t>=0 && r<maxY && map[t][r]==0 && map[t][y]==0 && map[x][r]==0) this.chkPoint(_node,x,y,g,t,r,x1,y1);//3
  155.         if(l>=0 && map[x][l]==0) this.chkPoint(_node,x,y,g,x,y-1,x1,y1);//4
  156.         if(r<maxY && map[x][r]==0) this.chkPoint(_node,x,y,g,x,y+1,x1,y1);//6
  157.         if(b<maxX && l>=0 && map[b][l]==0 && map[x][l]==0 && map[b][y]==0) this.chkPoint(_node,x,y,g,b,l,x1,y1);//7
  158.         if(b<maxX && map[b][y]==0) this.chkPoint(_node,x,y,g,x+1,y,x1,y1);//8
  159.         if(b<maxX && r<maxY && map[b][r]==0 && map[b][y]==0 && map[x][r]==0) this.chkPoint(_node,x,y,g,b,r,x1,y1);//9
  160.     }
  161.     //检测子节点对象
  162.     this.chkPoint = function(_fnode,_x0,_y0,_g,_x1,_y1,_x2,_y2){
  163.         var open = this.openList;
  164.         var chk = this.chkList;
  165.         var _id = new String(_x1+'_'+_y1);
  166.         var _point = null;
  167.         if(undefined == (_point = chk[_id])){
  168.             _point = new this.point(0,0,0,_x1,_y1,_fnode);
  169.             open[open.length] = _point;
  170.             chk[_id] = _point;
  171.             _point.g = _g + this.getG(_x0,_y0,_x1,_y1); //起点到当前点实际值
  172.             _point.h = this.getH(_x1,_y1,_x2,_y2);      //终点到当前点的估价
  173.             _point_point.f = _point.g + _point.h;
  174.         }else{
  175.             var _CNG = _g + this.getG(_x0,_y0,_x1,_y1);
  176.             if(_point.g>_CNG){//保留小G,替换parentNode
  177.                 _point.g = _CNG;
  178.                 _point_point.f = _point.g + _point.h;
  179.                 _point.p = _fnode;
  180.             }
  181.         }
  182.     }
  183.     //探索路径
  184.     this.getPath = function(x0,y0,x1,y1){
  185.         var st = new Date();
  186.         var tp = [];
  187.         var open = this.openList;
  188.         var map = this.map;
  189.         if(map[x0][y0]!=0 || map[x1][y1]!=0){
  190.             return tp;
  191.         }
  192.         var _sh = this.getH(x0,y0,x1,y1);
  193.         open[0] = new this.point(_sh,0,_sh,x0,y0,null);
  194.         var oll=0,nowNode=null;
  195.         while(0<(oll=open.length)){
  196.             var maxNode,minIndex,minf=10000000000;
  197.             for(var i=0;i<oll;i++){
  198.                 maxNode = open[i];
  199.                 if(minf>maxNode.f){
  200.                     minf = maxNode.f;
  201.                     minIndex = i;
  202.                 }
  203.             }
  204.             nowNode = open[minIndex];
  205.             open[minIndex] = open[oll-1];
  206.             open.length--;
  207.             if(nowNode.x==x1 && nowNode.y==y1){
  208.                 while(nowNode.p!=null){
  209.                     tp.push([nowNode.x,nowNode.y]);
  210.                     nowNodenowNode = nowNode.p;
  211.                 }
  212.                 tp.push([x0,y0]);
  213.                 break;
  214.             }
  215.             this.setPoints(nowNode,x1,y1);
  216.         }
  217.         open = this.openList = this.chkList = map = [];
  218.         document.title = new Date()-st+' ms, '+tp.length+'steps.';
  219.         return tp.slice(0).reverse();
  220.     }
  221. }
  222. var maps = [ // handest
  223.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  224.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  225.     [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  226.     [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  227.     [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  228.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  229.     [0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  230.     [0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  231.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  232.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  233.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  234.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  235.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  236.     [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  237.     [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  238.     [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  239.     [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  240.     [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  241.     [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  242.     [0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  243.     [0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  244.     [0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  245.     [0,0,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  246.     [0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  247.     [0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  248.     [0,0,1,1,1,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  249.     [0,0,0,0,1,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  250.     [0,0,0,0,1,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
  251.     [0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
  252.     [0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0],
  253.     [0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,1,0,1,0,0,1,0,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
  254.     [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
  255.     [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0],
  256.     [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0],
  257.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0],
  258.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,1,1,0,0,1,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0],
  259.     [0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0],
  260.     [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0],
  261.     [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
  262.     [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
  263.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
  264.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0],
  265.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],
  266.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],
  267.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],
  268.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],
  269.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0],
  270.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0],
  271.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0],
  272.     [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
  273. ];
  274. map.call(maps);
  275. maps.setView();
  276. Astar.call(maps,maps);
  277. </script>
  278. <h1>Javascript版A*(a star)算法!</h1>
  279. <h3>在白色表格中点击,第一次设置起点,第二次设置终点,将自动找到路径!</h3>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红火吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值