A*寻路算法 javascript版本

去年做一个模仿保卫萝卜的塔防游戏的时候,自己写的,游戏框架用的是coco2d-html5

实现原理可以参考 http://www.cnblogs.com/technology/archive/2011/05/26/2058842.html

这个算法项目一直放在github中,朋友们需要的可以自己去看下

https://github.com/caoke90/Algorithm/blob/master/Astar.js

//Astar 寻路算法
//Point 类型
var cc=cc||console
var Point=function(x,y){
    if(this instanceof Point){
        this.init(x,y)
    }else{
        return new Point(x,y)
    }

}
Point.prototype={
    init:function(x,y){
        this.x=x;
        this.y=y;
    },
    ParentPoint:null,
    F :0,  //F=G+H
    G:0,
    H:0,
    x:0,
    y:0,
    CalcF:function(){
        this.F = this.G + this.H;
    }
}

//Maze 类型
var Maze=function(maze){
    if(this instanceof Maze){
        this.init(maze);
    }else{
        return new Maze(maze)
    }
}
Maze.prototype={
    init:function(maze){
        this.MazeArray=maze
    },
    OBLIQUE : 14,
    STEP:10,
    CloseList:[],
    OpenList:[],
    FindPath:function(start, end, IsIgnoreCorner){
        this.OpenList.push(start);
        while (this.OpenList.length != 0)
        {
            //找出F值最小的点
            var tempStart = this.MinPoint(this.OpenList);
            this.CloseList.push(tempStart);
            this.Remove(this.OpenList,tempStart);

            //找出它相邻的点
            var surroundPoints = this.SurrroundPoints(tempStart, IsIgnoreCorner);
            for (var i=0;i< surroundPoints.length;i++)
            {
                var point=surroundPoints[i]
                if (this.Exists(this.OpenList,point)){
                    //计算G值, 如果比原来的大, 就什么都不做, 否则设置它的父节点为当前点,并更新G和F
                    this.FoundPoint(tempStart, point);
                }
                else{
                    //如果它们不在开始列表里, 就加入, 并设置父节点,并计算GHF
                    this.NotFoundPoint(tempStart, end, point);
                }
            }
            if (this.Get(this.OpenList,end) != null){
                return this.Get(this.OpenList,end);
            }
        }
        return this.Get(this.OpenList,end);
    },
    //在二维数组对应的位置不为障碍物
    CanReaches:function(x,y){
        return this.MazeArray[this.MazeArray.length-y-1][x] == 0;
    },
    CanReach:function( start, point, IsIgnoreCorner){
        if (!this.CanReaches(point.x, point.y) || this.Exists(this.CloseList,point))
            return false;
        else
        {
            if ((Math.abs(point.x - start.x) + Math.abs(point.y - start.y)) == 1){
                return true;
            }
            return false;
        }
    },
    NotFoundPoint:function(tempStart, end, point){
        point.ParentPoint = tempStart;
        point.G = this.CalcG(tempStart, point);
        point.H = this.CalcH(end, point);
        point.CalcF();
        this.OpenList.push(point);

    },
    FoundPoint:function(tempStart, point){
        var G = this.CalcG(tempStart, point);
        if (G < point.G)
        {
            point.ParentPoint = tempStart;
            point.G = G;
            point.CalcF();
        }
    },
    CalcG:function(start, point)
    {
        var G = (Math.abs(point.X - start.X) + Math.abs(point.Y - start.Y)) == 2 ? this.OBLIQUE:this.STEP ;
        var parentG = point.ParentPoint != null ? point.ParentPoint.G : 0;
        return G + parentG;
    },

    CalcH:function( end,  point)
    {
        var step = Math.abs(point.x - end.x) + Math.abs(point.y - end.y);
        return step * this.STEP;
    },

//获取某个点周围可以到达的点
    SurrroundPoints:function( point,  IsIgnoreCorner)
    {
        var surroundPoints = [];
        if (this.CanReach(point,Point(point.x-1,point.y),IsIgnoreCorner)){
            surroundPoints.push(Point(point.x-1,point.y));
        }
        if (this.CanReach(point,Point(point.x,point.y-1),IsIgnoreCorner)){
            surroundPoints.push(Point(point.x,point.y-1));
        }
        if (this.CanReach(point,Point(point.x+1,point.y),IsIgnoreCorner)){
            surroundPoints.push(Point(point.x+1,point.y));
        }
        if (this.CanReach(point,Point(point.x,point.y+1),IsIgnoreCorner)){
            surroundPoints.push(Point(point.x,point.y+1));
        }
        return surroundPoints;
    },


//对 List<Point> 的一些扩展方法
//判断是否存在点
    Exists:function(points, point)
    {
        for(k in points){
            var p=points[k]
            if ((p.x == point.x) && (p.y == point.y)){
                return true;
            }
        }
        return false;
    },
//获取f最小
    MinPoint:function (points)
    {
        var min=points[0];
        for(var i=0;i<points.length-1;i++){
            if(points[i].F<points[i+1].F){
                min=points[i]
            }
        }
        return min;
    },
//获取点
    Get:function(points, point)
    {
        for (var k in points){
            var p=points[k]
            if ((p.x == point.x) && (p.y == point.y))
                return p;
        }
        return null;
    },
//删除点
    Remove:function(points,point)
    {
        for(var i=0;i<points.length;i++){
            var p=points[i]
            if (point.x === p.x && point.y === p.y){
                return points.splice(i,1);
            }
        }

    }

}

var arr= [
    [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [ 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [ 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [ 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [ 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [ 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
];

var map=Maze(arr)
//起始点 结束点 是否斜角
var parent=map.FindPath(Point(2,3),Point(16,2),false)

while (parent != null)
{
    cc.log(parent.x + ", " + parent.y);
    parent = parent.ParentPoint;
}

  

原文地址:https://www.cnblogs.com/caoke/p/4204163.html