请在这里查看示例 ☞ aStar示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>demo</title>
<script src="../js/jquery-1.11.3.min.js"></script>
<style>
* {margin: 0; padding: 0; font-size: 5px;}
div {display: inline-block; outline: 1px solid blue; width: 20px; height: 20px; position: absolute; text-align: center; line-height: 20px;}
.s {background: green; outline: none; z-index: 1;}
.e {background: red; outline: none; z-index: 1;}
.o {background: grey; outline: none;}
.m {background: yellow; outline: none;}
.b {background: purple; outline: none;}
.w {background: black; outline: none;}
</style>
</head>
<body>
<p>灰色 - 障碍物</p>
<p>黄色 - 已遍历块</p>
<p>紫色 - 待遍历块</p>
<p>黑色 - 最短路径</p>
<script>
$(function() {
var unit = 20;
var sArr = [5, 4];
var eArr = [30, 14];
var oArr = [
[5, 3],
[6, 4],
[5, 5],
[3, 7],
[4, 7],
[5, 7],
[6, 7],
[7, 6],
[9, 4],
[9, 5],
[9, 6],
[9, 7],
[7, 10],
[8, 10],
[9, 10],
[10, 10],
[27, 13],
[27, 14],
[27, 15],
[20, 10],
[20, 11],
[20, 12],
[17, 14],
[18, 14],
[19, 14],
[20, 14],
[19, 15],
[19, 16],
[28, 13],
[29, 13],
[30, 13],
[31, 13],
[27, 17],
];
//[,,G,H,F]
sArr.push(0);
sArr.push(Math.abs(sArr[0]-eArr[0])+Math.abs(sArr[1]-eArr[1]));
sArr.push(Math.abs(sArr[0]-eArr[0])+Math.abs(sArr[1]-eArr[1]));
var $sDiv = $('<div class="s">').css({
left: sArr[0]*unit,
top: sArr[1]*unit,
}).text(sArr).appendTo('body');
var $eDiv = $('<div class="e">').css({
left: eArr[0]*unit,
top: eArr[1]*unit,
}).text(eArr).appendTo('body');
for(var i=0; i<oArr.length; i++) {
var $oDiv = $('<div class="o">').css({
left: oArr[i][0]*unit,
top: oArr[i][1]*unit,
}).text(oArr[i]).appendTo('body');
}
var openList = [];
var closeList = [];
function aStar() {
var proArr = [];
closeList.push(sArr);
while(!(closeList[closeList.length-1][0]==eArr[0] && closeList[closeList.length-1][1]==eArr[1])) {
proArr = getProArr(closeList[closeList.length-1]);//获取下一次的位置
for(var i=0; i<proArr.length; i++) {
openList.push(proArr[i]);
/*var $div = $('<div class="m">').css({
left: closeList[closeList.length-1][0]*unit,
top: closeList[closeList.length-1][1]*unit,
}).appendTo('body');*/
}
openList.sort(function(a, b) {
return a[4] - b[4];
});
closeList.push(openList[0]);
openList.splice(0, 1);
/*var $div = $('<div class="b">').css({
left: closeList[closeList.length-1][0]*unit,
top: closeList[closeList.length-1][1]*unit,
}).appendTo('body');*/
}
/*for(var i=0; i<closeList.length; i++) {
var $div = $('<div class="m">').css({
left: closeList[i][0]*unit,
top: closeList[i][1]*unit,
}).appendTo('body');
}*/
var findArr = [];
var curArr = closeList[closeList.length-1];
findArr.push(curArr);
closeList.splice(closeList.length-1, 1);
//return;
while(!(curArr[5]==sArr[0] && curArr[6]==sArr[1])) {
for(var i=0; i<closeList.length; i++) {
if(curArr[5]==closeList[i][0] && curArr[6]==closeList[i][1]) {
curArr = closeList[i];
findArr.push(closeList[i]);
closeList.splice(i, 1);
break;
}
}
}
//.s 起点 .e 终点 .o 墙 .m 考虑过的 .b 待考虑的 .w 最短路径
for(var i=0; i<openList.length; i++) {
var $div = $('<div class="b">').css({
left: openList[i][0]*unit,
top: openList[i][1]*unit,
}).appendTo('body');
}
for(var i=0; i<closeList.length; i++) {
var $div = $('<div class="m">').css({
left: closeList[i][0]*unit,
top: closeList[i][1]*unit,
}).appendTo('body');
}
for(var i=0; i<findArr.length; i++) {
var $div = $('<div class="w">').css({
left: findArr[i][0]*unit,
top: findArr[i][1]*unit,
}).appendTo('body');
}
}
aStar();
function getProArr(arr) {//获取下一次的位置
var allArr = [//上右下左
[arr[0], arr[1]-1, arr[2]+1, Math.abs((arr[0])-(eArr[0]))+Math.abs((arr[1]-1)-(eArr[1])), arr[2]+1+Math.abs((arr[0])-(eArr[0]))+Math.abs((arr[1]-1)-(eArr[1])), arr[0], arr[1]],
[arr[0]+1, arr[1], arr[2]+1, Math.abs((arr[0]+1)-(eArr[0]))+Math.abs((arr[1])-(eArr[1])), arr[2]+1+Math.abs((arr[0]+1)-(eArr[0]))+Math.abs((arr[1])-(eArr[1])), arr[0], arr[1]],
[arr[0], arr[1]+1, arr[2]+1, Math.abs((arr[0])-(eArr[0]))+Math.abs((arr[1]+1)-(eArr[1])), arr[2]+1+Math.abs((arr[0])-(eArr[0]))+Math.abs((arr[1]+1)-(eArr[1])), arr[0], arr[1]],
[arr[0]-1, arr[1], arr[2]+1, Math.abs((arr[0]-1)-(eArr[0]))+Math.abs((arr[1])-(eArr[1])), arr[2]+1+Math.abs((arr[0]-1)-(eArr[0]))+Math.abs((arr[1])-(eArr[1])), arr[0], arr[1]],
//左上 右上 右下 左下
[arr[0]-1, arr[1]-1, arr[2]+1.4, Math.abs((arr[0]-1)-(eArr[0]))+Math.abs((arr[1]-1)-(eArr[1])), arr[2]+1.4+Math.abs((arr[0]-1)-(eArr[0]))+Math.abs((arr[1]-1)-(eArr[1])), arr[0], arr[1]],
[arr[0]+1, arr[1]-1, arr[2]+1.4, Math.abs((arr[0]+1)-(eArr[0]))+Math.abs((arr[1]-1)-(eArr[1])), arr[2]+1.4+Math.abs((arr[0]+1)-(eArr[0]))+Math.abs((arr[1]-1)-(eArr[1])), arr[0], arr[1]],
[arr[0]+1, arr[1]+1, arr[2]+1.4, Math.abs((arr[0]+1)-(eArr[0]))+Math.abs((arr[1]+1)-(eArr[1])), arr[2]+1.4+Math.abs((arr[0]+1)-(eArr[0]))+Math.abs((arr[1]+1)-(eArr[1])), arr[0], arr[1]],
[arr[0]-1, arr[1]+1, arr[2]+1.4, Math.abs((arr[0]-1)-(eArr[0]))+Math.abs((arr[1]+1)-(eArr[1])), arr[2]+1.4+Math.abs((arr[0]-1)-(eArr[0]))+Math.abs((arr[1]+1)-(eArr[1])), arr[0], arr[1]],
];
//除去closeList中已有(先去closeList后去障碍)
for(var i=0; i<closeList.length; i++) {
for(var j=0; j<allArr.length; j++) {
if((closeList[i][0]==allArr[j][0] && closeList[i][1]==allArr[j][1])) {
allArr.splice(j, 1);
}
}
}
//除去障碍且斜45°有墙角时禁止通过(先去closeList后去障碍)
for(var i=0; i<oArr.length; i++) {
for(var j=0; j<allArr.length; j++) {
if((oArr[i][0]==allArr[j][0] && oArr[i][1]==allArr[j][1]) || (Math.abs(allArr[j][0]-oArr[i][0])+Math.abs(allArr[j][1]-oArr[i][1])==1 && Math.abs(arr[0]-oArr[i][0])+Math.abs(arr[1]-oArr[i][1])==1)) {
allArr.splice(j, 1);
}
}
}
return allArr;
}
})
</script>
</body>
</html>