这里是清单执行JavaScript


  1. var astar = {  
  2.     init: function(grid) {  
  3.         for(var x = 0; x < grid.length; x++) {  
  4.             for(var y = 0; y < grid[x].length; y++) {  
  5.                 grid[x][y].f = 0;  
  6.                 grid[x][y].g = 0;  
  7.                 grid[x][y].h = 0;  
  8.                 grid[x][y].debug = "";  
  9.                 grid[x][y].parent = null;  
  10.             }     
  11.         }  
  12.     },  
  13.     search: function(grid, start, end) {  
  14.         astar.init(grid);  
  15.    
  16.         var openList   = [];  
  17.         var closedList = [];  
  18.         openList.push(start);  
  19.    
  20.         while(openList.length > 0) {  
  21.    
  22.             // Grab the lowest f(x) to process next  
  23.             var lowInd = 0;  
  24.             for(var i=0; i<openList.length; i++) {  
  25.                 if(openList[i].f < openList[lowInd].f) { lowInd = i; }  
  26.             }  
  27.             var currentNode = openList[lowInd];  
  28.    
  29.             // End case -- result has been found, return the traced path  
  30.             if(currentNode.pos == end.pos) {  
  31.                 var curr = currentNode;  
  32.                 var ret = [];  
  33.                 while(curr.parent) {  
  34.                     ret.push(curr);  
  35.                     curr = curr.parent;  
  36.                 }  
  37.                 return ret.reverse();  
  38.             }  
  39.    
  40.             // Normal case -- move currentNode from open to closed, process each of its neighbors  
  41.             openList.removeGraphNode(currentNode);  
  42.             closedList.push(currentNode);  
  43.             var neighbors = astar.neighbors(grid, currentNode);  
  44.    
  45.             for(var i=0; i<neighbors.length;i++) {  
  46.                 var neighbor = neighbors[i];  
  47.                 if(closedList.findGraphNode(neighbor) || neighbor.isWall()) {  
  48.                     // not a valid node to process, skip to next neighbor  
  49.                     continue;  
  50.                 }  
  51.    
  52.                 // g score is the shortest distance from start to current node, we need to check if  
  53.                 //   the path we have arrived at this neighbor is the shortest one we have seen yet  
  54.                 var gScore = currentNode.g + 1; // 1 is the distance from a node to it's neighbor  
  55.                 var gScoreIsBest = false;  
  56.    
  57.    
  58.                 if(!openList.findGraphNode(neighbor)) {  
  59.                     // This the the first time we have arrived at this node, it must be the best  
  60.                     // Also, we need to take the h (heuristic) score since we haven't done so yet  
  61.    
  62.                     gScoreIsBest = true;  
  63.                     neighbor.h = astar.heuristic(neighbor.pos, end.pos);  
  64.                     openList.push(neighbor);  
  65.                 }  
  66.                 else if(gScore < neighbor.g) {  
  67.                     // We have already seen the node, but last time it had a worse g (distance from start)  
  68.                     gScoreIsBest = true;  
  69.                 }  
  70.    
  71.                 if(gScoreIsBest) {  
  72.                     // Found an optimal (so far) path to this node.  Store info on how we got here and  
  73.                     //  just how good it really is...  
  74.                     neighbor.parent = currentNode;  
  75.                     neighbor.g = gScore;  
  76.                     neighbor.f = neighbor.g + neighbor.h;  
  77.                     neighbor.debug = "F: " + neighbor.f + "<br />G: " + neighbor.g + "<br />H: " + neighbor.h;  
  78.                 }  
  79.             }  
  80.         }  
  81.    
  82.         // No result was found -- empty array signifies failure to find path  
  83.         return [];  
  84.     },  
  85.     heuristic: function(pos0, pos1) {  
  86.         // This is the Manhattan distance  
  87.         var d1 = Math.abs (pos1.x - pos0.x);  
  88.         var d2 = Math.abs (pos1.y - pos0.y);  
  89.         return d1 + d2;  
  90.     },  
  91.     neighbors: function(grid, node) {  
  92.         var ret = [];  
  93.         var x = node.pos.x;  
  94.         var y = node.pos.y;  
  95.    
  96.         if(grid[x-1] && grid[x-1][y]) {  
  97.             ret.push(grid[x-1][y]);  
  98.         }  
  99.         if(grid[x+1] && grid[x+1][y]) {  
  100.             ret.push(grid[x+1][y]);  
  101.         }  
  102.         if(grid[x][y-1] && grid[x][y-1]) {  
  103.             ret.push(grid[x][y-1]);  
  104.         }  
  105.         if(grid[x][y+1] && grid[x][y+1]) {  
  106.             ret.push(grid[x][y+1]);  
  107.         }  
  108.         return ret;  
  109.     }  


};  

这里是一个快速的实现,使用二进制堆而不是一个列表。这是快了很多,还包括选择搜索对角–8定向运动。图搜索项目页面以获取最新的代码版本

  1. var astar = {  
  2.     init: function(grid) {  
  3.         for(var x = 0, xl = grid.length; x < xl; x++) {  
  4.             for(var y = 0, yl = grid[x].length; y < yl; y++) {  
  5.                 var node = grid[x][y];  
  6.                 node.f = 0;  
  7.                 node.g = 0;  
  8.                 node.h = 0;  
  9.                 node.cost = 1;  
  10.                 node.visited = false;  
  11.                 node.closed = false;  
  12.                 node.parent = null;  
  13.             }  
  14.         }  
  15.     },  
  16.     heap: function() {  
  17.         return new BinaryHeap(function(node) {   
  18.             return node.f;   
  19.         });  
  20.     },  
  21.     search: function(grid, start, end, diagonal, heuristic) {  
  22.         astar.init(grid);  
  23.         heuristic = heuristic || astar.manhattan;  
  24.         diagonal = !!diagonal;  
  25.    
  26.         var openHeap = astar.heap();  
  27.    
  28.         openHeap.push(start);  
  29.    
  30.         while(openHeap.size() > 0) {  
  31.    
  32.             // Grab the lowest f(x) to process next.  Heap keeps this sorted for us.  
  33.             var currentNode = openHeap.pop();  
  34.    
  35.             // End case -- result has been found, return the traced path.  
  36.             if(currentNode === end) {  
  37.                 var curr = currentNode;  
  38.                 var ret = [];  
  39.                 while(curr.parent) {  
  40.                     ret.push(curr);  
  41.                     curr = curr.parent;  
  42.                 }  
  43.                 return ret.reverse();  
  44.             }  
  45.    
  46.             // Normal case -- move currentNode from open to closed, process each of its neighbors.  
  47.             currentNode.closed = true;  
  48.    
  49.             // Find all neighbors for the current node. Optionally find diagonal neighbors as well (false by default).  
  50.             var neighbors = astar.neighbors(grid, currentNode, diagonal);  
  51.    
  52.             for(var i=0, il = neighbors.length; i < il; i++) {  
  53.                 var neighbor = neighbors[i];  
  54.    
  55.                 if(neighbor.closed || neighbor.isWall()) {  
  56.                     // Not a valid node to process, skip to next neighbor.  
  57.                     continue;  
  58.                 }  
  59.    
  60.                 // The g score is the shortest distance from start to current node.  
  61.                 // We need to check if the path we have arrived at this neighbor is the shortest one we have seen yet.  
  62.                 var gScore = currentNode.g + neighbor.cost;  
  63.                 var beenVisited = neighbor.visited;  
  64.    
  65.                 if(!beenVisited || gScore < neighbor.g) {  
  66.    
  67.                     // Found an optimal (so far) path to this node.  Take score for node to see how good it is.  
  68.                     neighbor.visited = true;  
  69.                     neighbor.parent = currentNode;  
  70.                     neighbor.h = neighbor.h || heuristic(neighbor.pos, end.pos);  
  71.                     neighbor.g = gScore;  
  72.                     neighbor.f = neighbor.g + neighbor.h;  
  73.    
  74.                     if (!beenVisited) {  
  75.                         // Pushing to heap will put it in proper place based on the 'f' value.  
  76.                         openHeap.push(neighbor);  
  77.                     }  
  78.                     else {  
  79.                         // Already seen the node, but since it has been rescored we need to reorder it in the heap  
  80.                         openHeap.rescoreElement(neighbor);  
  81.                     }  
  82.                 }  
  83.             }  
  84.         }  
  85.    
  86.         // No result was found - empty array signifies failure to find path.  
  87.         return [];  
  88.     },  
  89.     manhattan: function(pos0, pos1) {  
  90.         // See list of heuristics: http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html  
  91.    
  92.         var d1 = Math.abs (pos1.x - pos0.x);  
  93.         var d2 = Math.abs (pos1.y - pos0.y);  
  94.         return d1 + d2;  
  95.     },  
  96.     neighbors: function(grid, node, diagonals) {  
  97.         var ret = [];  
  98.         var x = node.x;  
  99.         var y = node.y;  
  100.    
  101.         // West  
  102.         if(grid[x-1] && grid[x-1][y]) {  
  103.             ret.push(grid[x-1][y]);  
  104.         }  
  105.    
  106.         // East  
  107.         if(grid[x+1] && grid[x+1][y]) {  
  108.             ret.push(grid[x+1][y]);  
  109.         }  
  110.    
  111.         // South  
  112.         if(grid[x] && grid[x][y-1]) {  
  113.             ret.push(grid[x][y-1]);  
  114.         }  
  115.    
  116.         // North  
  117.         if(grid[x] && grid[x][y+1]) {  
  118.             ret.push(grid[x][y+1]);  
  119.         }  
  120.    
  121.         if (diagonals) {  
  122.    
  123.             // Southwest  
  124.             if(grid[x-1] && grid[x-1][y-1]) {  
  125.                 ret.push(grid[x-1][y-1]);  
  126.             }  
  127.    
  128.             // Southeast  
  129.             if(grid[x+1] && grid[x+1][y-1]) {  
  130.                 ret.push(grid[x+1][y-1]);  
  131.             }  
  132.    
  133.             // Northwest  
  134.             if(grid[x-1] && grid[x-1][y+1]) {  
  135.                 ret.push(grid[x-1][y+1]);  
  136.             }  
  137.    
  138.             // Northeast  
  139.             if(grid[x+1] && grid[x+1][y+1]) {  
  140.                 ret.push(grid[x+1][y+1]);  
  141.             }  
  142.    
  143.         }  
  144.    
  145.         return ret;  
  146.     }  
  147. };