A*算法实现

请在这里查看示例 ☞ 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>


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值