和谐的望天

如今已到了风烛残年的岁月,想起还有许多未看未发觉的动画就不由的老泪纵横啊.<<返回空间主页装扮空间查看主人装扮自定义送礼物加为好友设置个人中心

原创  JavaScript实现AStar算法 收藏

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>A-Star</title>
<script type="text/javascript">
/*
蛮好玩的东西。。。
严重感谢winter。。。
*/

var AStar = function () {
    this.tmin = -1;   //上部搜索最小值(不包括)
    this.rmax = -1;   //右部搜索最大值(不包括)
    this.bmax = -1;   //下部搜索最大值(不包括)
    this.lmin = -1;   //左部搜索最小值(不包括)
    this.initialize();
};

AStar.prototype = {

    constructor : AStar
   
    , pointSource : function () {
    //获取点对象构造的引用
        return this.constructor.Point;
    }
   
    , euclidean : function (a, b) {
        with (Math) { return round(10 * sqrt(pow(a.X - b.X, 2) + pow(a.Y - b.Y, 2))); }
    }
   
    , manhattan : function (a, b) {
        with (Math) { return abs(a.X - b.X) + abs(a.Y - b.Y); }
    }
   
    , initialize : function () {
    //初始化参数
        this.open = [];   //open表
        this.close = [];  //close表
        this.maps = {};  //已经发现点组
    }
   
    , makeID : function (x, y, limit) {
    //创造ID
        return x + y * limit;
    }
   
    , getMinNode : function () {
    //获取最佳节点
        var i = 1, o = this.open, l = o.length, min = i - 1, max = o[0].F, t = null;

        for (; i < l ; i ++) {
            t = o[i];
            if (t.F < max) { max = t.F, min = i; }
        }
        t = o[min], o[min] = o[l - 1], o.pop();

        return t;
    }
   
    , getNodes : function (node) {
    //获取子节点
        var map = this.Map, tmin = this.tmin, rmax = this.rmax, bmax = this.bmax, lmin = this.lmin, nodes = []
            , x = node.X, y = node.Y, t = y - 1, r = x + 1, b = y + 1, l = x - 1
            , _t = t > tmin && (map[t][x] === 0)
            , _r = r < rmax && (map[y][r] === 0)
            , _b = b < bmax && (map[b][x] === 0)
            , _l = l > lmin && (map[y][l] === 0), i = 0;
       
        if (_t) {
            nodes[i++] = [x, t];
            if (_l && (map[t][l] === 0)) nodes[i++] = [l, t];
            if (_r && (map[t][r] === 0)) nodes[i++] = [r, t];
        }
       
        if (_l) nodes[i++] = [l, y];
       
        if (_b) {
            nodes[i++] = [x, b];
            if (_l && (map[b][l] === 0)) nodes[i++] = [l, b];
            if (_r && (map[b][r] === 0)) nodes[i++] = [r, b];
        }
       
        if (_r) nodes[i++] = [r, y];
       
        return nodes;
    }
   
    , getAllPath : function (node) {
    //获取完整路径
        var path = [];
        do {
            path[path.length] = [node.X, node.Y];
        } while (node = node.P);
        path.reverse(), this.initialize();
       
        return path;
    }
   
    , loadMap : function (map) {
    //加载地图
        this.Map = map;
        this.limit = (this.bmax = map.length) * (this.rmax = map[0].length);
    }
   
    , search : function (start, goal) {
    //搜索
       
        var Point = this.pointSource()
            , open = this.open, close = this.close
            , makeID = this.makeID //放创造唯一值函数的引用.这样快
            , maps = this.maps //地图
            , limit = this.limit //地图最大值
            , euclidean = this.euclidean //计算代价的方法
            , GID = makeID(goal.X, goal.Y, limit) //终点的唯一值
            , nodes = []
            , length = 0
            , node = null, tempnode = null, tempg = 0
            , id = 0, i = 0, j = 0, _i = 0, _j = 0;
       
        open.push(new Point(null, start.X, start.Y)); //追加启始点
       
        while (length = open.length) {
            node = this.getMinNode(); //取最优点
           
            if (node.I != GID) { //若不是终点
               
                nodes = this.getNodes(node); //取该点所有所有临点
               
                for (i = 0, j = nodes.length ; i < j ; i ++) {
                    id = makeID(nodes[i][0], nodes[i][1], limit); //获取临点ID
                   
                    if (!(tempnode = maps[id])) { //如果没有查过
                        //创建点对象.放到open表.放到关联组
                        tempnode = open[open.length] = maps[id] = new Point(node, nodes[i][0], nodes[i][1]);
                        //计算代价值,估价值,总值
                        tempnode.F =
                            (tempnode.G = node.G + euclidean(tempnode, node)) + (tempnode.H = euclidean(tempnode, goal));
                        tempnode.I = id; //计算唯一标识
                    } else { //如果存在此点
                        tempg = node.G + euclidean(tempnode, node); //计算当前点到此临点的G值
                       
                        //如果此G值小于此临点的G值那么把这个临点抢过来。。。然后重新初始化一些参数
                        if (tempg < tempnode.G) tempnode.P = node, tempnode.G = tempg, tempnode.F = tempg + tempnode.H;
                    }
                }
               
                close[close.length] = node; //放入close表
            } else {
                return this.getAllPath(node); //已经找到最优路径.返回完整路径
            }
        }
        return (this.initialize(), []); //没有找到最优路径.返回空值
    }

};

AStar.Point = function (p, x, y) {
//节点
    this.P = p;  //父节点
    this.X = x;  //x位置
    this.Y = y;  //y位置
    this.G = 0;  //g值
    this.H = 0;  //h值
    this.F = 0;  //f值
    this.I = 0;  //节点唯一值
};

var getPath = function () {
//获取路径
    return path.length > 0 ? path.shift() : null;
};

var loadMap = function () {
//加载地图
    var r, c, rary, cary;
   
    for (rary = [], r = 0 ; r < maps.length ; r ++) {
        for (cary = [], c = 0 ; c < maps[r].length ; c ++) {
            if (maps[r][c] == 0) {
                cary[c] = '#FFFFFF';
            } else {
                cary[c] = '#FFF000';
            }
        }
        rary[r] = '<td bgColor="' + cary.join('">&nbsp;<\/td><td bgColor="') + '">&nbsp;<\/td>'
    }
    document.body.innerHTML = '<table id="maps"><tr>' + rary.join('<\/tr><tr>') + '<\/tr><\/table>';
};

var resizeMap = function () {
//重置地图
    var table = document.getElementById('maps'), r, c;
   
    for (r = 0 ; r < table.rows.length ; r ++) {
        for (c = 0 ; c < table.rows[r].cells.length ; c ++) {
            table.rows[r].cells[c].bgColor = (maps[r][c] == 0 ? '#FFFFFF' : '#FFF000');
        }
    }
};

var goGoal = function (start, end) {
//查找路径
    var t = new Date;
    path = wc.search(start, end);
    document.title = new Date() - t + 'ms';
    window.status = path.length;

    if (path.length > 2) {
        path = path.slice(1, -1);
        moveToGoal();
    }
};

var moveToGoal = function () {
//设置走路:D
    var temp;
    if (path.length > 0) {
        temp = path.shift();
        document.getElementById('maps').rows[temp[1]].cells[temp[0]].bgColor = '#FF0000';
        window.setTimeout(arguments.callee, 30);
    }
};


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

var wc = new AStar; //创建ASatr对象
wc.loadMap(maps); //载入地图


window.onload = function () {
    var sn = 0;
    var start = { x : 0, y : 0 }, end = { x : 0, y : 0 };
   
    loadMap(); //显示地图
   
    var table = document.getElementById('maps');
   
    table.onmousedown = function (e) {
   
        var e = window.event || e;
   
        var obj = e.srcElement || e.target;
        if (obj.nodeName == 'TD') {
            if (sn) {
                end.X = obj.cellIndex, end.Y = obj.parentNode.rowIndex;
                obj.bgColor = '#000000';
                window.setTimeout(function () {
                    goGoal(start, end);
                }, 0);
            } else {
                resizeMap();
                obj.bgColor = '#000000';
                start.X = obj.cellIndex, start.Y = obj.parentNode.rowIndex;
            }
            sn = Math.abs(sn - 1);
        }
    };
};
</script>
<style type="text/css">
table {
    border-left:#CCC 1px solid;
    border-top:#CCC 1px solid;
    border-collapse:collapse;
}
td {
    border-right:#CCC 1px solid;
    border-bottom:#CCC 1px solid;
    height:10px;
    width:10px;
    font-size:0;
}
</style>
</head>
<body>
</body>
</html>

发表于 @ 2008年04月02日 20:20:00 | 评论( loading... ) | 编辑| 举报| 收藏

旧一篇:愚人节小程序.... | 新一篇:with配合eval可改变function[[scope]]

  • 发表评论
  • 评论内容:
  •  
Copyright © muxrwc
Powered by CSDN Blog