1. 程式人生 > >js尋路算法

js尋路算法

als div arr 遞歸 function margin 線路 length FN

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>

    

js尋路算法