js寻路算法
f()=g()+h(); //g为每个节点到起点得距离;h为每个节点到终点得距离。两个距离通过勾股定理可以算出;
以下代码基本的解释和注释都有。不懂得可以留言哦
css
<style>
ul{
list-style: none;
margin: 0;
padding: 0;
border: 1px solid #f5f5f5;
border-right: none;
border-bottom: none;
margin: 100px auto;
}
ul li{
float: left;
border: solid 1px #f5f5f5;
border-left: none;
border-top: none;
display: inline-block;
background: black;
}
.start{
background: skyblue;
}
.end{
background: green;
}
.usual{
background: pink;
}
</style>
html
<body>
<ul id="map-ul"></ul>
<input id="btn" type="button" value="开始" />
</body>
js
<script>
var oUl = document.getElementById("map-ul");
var startBtn = document.getElementById("btn");
var Li = oUl.getElementsByTagName("li");
var beginLi = document.getElementsByClassName("start");
var endLi = document.getElementsByClassName("end");
var map = [
1,1,1,1,1,1,1,1,1,1,//0为起点;2为障碍物,3为终点
1,1,0,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,2,2,2,1,1,
1,1,1,1,1,2,1,1,1,1,
1,1,1,1,1,2,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,3,
1,1,1,1,1,1,1,1,1,1
];
var openArr = [];//可能要走的路线
var closeArr = [];//已经关闭的路线
var cols = Math.sqrt(map.length)
var sizeBox = 20;
//初始化
init()
function init(){
creatMap();//初始化地图
startBtn.onclick = function(){
openFn();
}
}
function creatMap(){
oUl.style.width = cols * (sizeBox + 1) + 1 + "px";
oUl.style.height = cols * (sizeBox + 1) + 1 + "px";
for (var i=0;i<map.length;i++) {
var oLi = document.createElement("li");
oLi.style.width = sizeBox + "px";
oLi.style.height = sizeBox + "px";
oUl.appendChild(oLi)
if (map[i] == 2) {
oLi.className = "usual"
closeArr.push(oLi)//障碍物添加到关闭得线路
} else if(map[i] == 0){
oLi.className = "start"
openArr.push(oLi)//起始点添加到要走得线路
}else if(map[i] == 3){
oLi.className = "end"
}
}
}
function f(nodeLi){//nodeLi每个li节点
return g(nodeLi) + h(nodeLi);//g为节点到初始位置的距离,h为节点到结束位置的距离
}
function g(nodeLi){
//勾股定理算出距离
var x = beginLi[0].offsetLeft - nodeLi.offsetLeft;
var y = beginLi[0].offsetTop - nodeLi.offsetTop;
return Math.sqrt(x*x+y*y);
}
function h(nodeLi){
var x = endLi[0].offsetLeft - nodeLi.offsetLeft;
var y = endLi[0].offsetTop - nodeLi.offsetTop;
return Math.sqrt(x*x+y*y);
}
function openFn(){
//以起始位置为可能要走的第一个Li
var nowLi = openArr.shift();
if(nowLi == endLi[0]){
showLine();
return;
}
closeFn(nowLi);//将找过得节点添加到关闭的路线
findLi(nowLi);//寻找第一个Li周围的可能要走的Li
openArr.sort(function(li1,li2){//将可能走得线路得节点通过距离从下到大排序。当下次循环得时候可以直接拿到上个最近得节点,
return li1.num - li2.num;
})
openFn();
}
function findLi(nowLi){
var result = [];//所有没走过的路线。去除closeArr里存在的路线
for (var i=0;i<Li.length;i++) {
if( filter(Li[i])){
result.push(Li[i])
}
}
function filter(Li){//如果closeArr里没有就添加到队列
for (var i=0;i<closeArr.length;i++) {
if(closeArr[i] == Li){
return false;
}
}
for (var i=0;i<openArr.length;i++) {
if(openArr[i] == Li){
return false;
}
}
return true;
}
//在所有没走过的节点找到与当前节点相邻的8个方向的节点
for(var i=0;i<result.length;i++){
if(Math.abs(nowLi.offsetLeft - result[i].offsetLeft)<=21&&Math.abs(nowLi.offsetTop - result[i].offsetTop)<=21){
result[i].num = f(result[i]);
result[i].parent = nowLi;//设置指针
openArr.push(result[i])
}
}
}
function showLine(){
var result = [];
var lastLi = closeArr.pop();
var iNow = 0;
findParent(lastLi);
function findParent(li){
result.unshift(li);
if( li.parent == beginLi[0] ){
return;
}
findParent(li.parent);//通过指针递归
console.log(li.parent)
}
for (var i=0;i<result.length;i++) {
result[i].style.backgroundColor = "plum";
}
}
function closeFn(nowLi){
closeArr.push(nowLi);
}
</script>