A星实施,没有找到最短路径问题

时间:2013-09-23 02:14:26

标签: actionscript-3 shortest-path a-star

我有代码可以找到从A点到B点的最短路径。为此,我使用的是A星变化。我使用二维数组来表示一个二维网格,但我的路径不采用对角线快捷方式,只有左,右,上和下。到目前为止一切正常,但它并不总能找到最短的路径。我想知道出了什么问题,为什么会出错,以及如何解决它。提前谢谢。

这是一张图片来说明究竟发生了什么:

A-Star gone wrong example

这是我的代码(路径查找类首先,然后是它的助手类):

BTW:数学向量只不过是一个几何点类,而且playerTileLocation和enemyTileLocation都只是与网格上的起始节点和结束节点相对应的点。另外,我使用AStarNode类作为地图上所有图块的节点,而不是常规对象。

package {
import src.Characters.Character;
import src.InGame.Map;
import src.Maths.MathVector;

public final class BaseAI {
// REPRESENTS UP, DOWN, RIGHT, AND LEFT OF ANY ONE NODE  
    private static const bordersOfNode:Array = new Array(
        new MathVector( -1, 0), new MathVector(1, 0), new MathVector(0, -1), new MathVector(0, 1));


    private var _player:Character;
    private var map:Map;

    private var playerTileLocation:MathVector;



    private var openList:Array;
    private var closedList:Array;
// 2D ARRAY OF MAP TILES (I DON'T USE HERE, BUT I PLAN TO IN FUTURE)  
    private var mapArray:Array;
    private var originNode:AStarNode;
    private var complete:Boolean;


    public function BaseAI(_player:Character,map:Map):void {
        this._player = _player;
        this.map = map;

        openList = new Array();
        closedList = new Array();
        mapArray = map.tiles;
    }
    public function get player():Character {
        return this._player;
    }

    public function calculatePlayerTileLocation():void {
        playerTileLocation = map.worldToTilePoint(player.groundPosition);
    }
//WILL EVENTUAL RETURN A DIRECTION FOR THE ENEMY TO TAKE THAT ITERATION (EVERY 1-2 SECONDS)  
    public function getDirection(enemy:Character):String {
        var enemyTileLocation:MathVector = map.worldToTilePoint(enemy.groundPosition);


        originNode = new AStarNode(enemyTileLocation, playerTileLocation);
        originNode.setAsOrigin();

        openList = [originNode];
        closedList = [];

        complete = false;
        var currentNode:AStarNode;
        var examiningNode:AStarNode;

        while (!complete) {

            openList.sortOn("F", Array.NUMERIC);
            currentNode = openList[0];
            closedList.push(currentNode);
            openList.splice(0, 1);

            for (var i in bordersOfNode) {
                examiningNode = new AStarNode(new MathVector(currentNode.X + bordersOfNode[i].x, currentNode.Y + bordersOfNode[i].y),playerTileLocation);

                if (map.isOpenTile(map.getTile(examiningNode.X, examiningNode.Y)) && !examiningNode.isThisInArray(closedList)) {
                    if (!examiningNode.isThisInArray(openList)) {
                        openList.push(examiningNode);
                        examiningNode.parentNode = currentNode;
                    }else {

                    }
                    if (examiningNode.X == playerTileLocation.x && examiningNode.Y == playerTileLocation.y) {
                        complete = true;
                        var done:Boolean = false;
                        var thisNode:AStarNode;
                        thisNode = examiningNode;
                        while (!done) {
                            if (thisNode.checkIfOrigin()) {
                                done = true;
                            }else {
                                thisNode = thisNode.parentNode;
                            }
                        }
                    }
                }
            }
        }
    }
}

}

package {
import src.Maths.MathVector;

internal final class AStarNode {
    private var _X:int;
    private var _Y:int;

    private var _G:int;
    private var _H:int;
    private var _F:int;
    private var _parentNode:AStarNode;

    private var _isOrigin:Boolean;

    public static const VERTICAL:uint = 10;

    public function AStarNode(thisNodeLocation:MathVector, targetNodeLocation:MathVector) {
        X = thisNodeLocation.x;
        Y = thisNodeLocation.y;
        H = Math.abs(X - targetNodeLocation.x) + Math.abs(Y - targetNodeLocation.y);
        G = 0;
        F = H + G;
    }

    public function set X(newX:int):void {
        this._X = newX;
    }
    public function get X():int {
        return this._X;
    }

    public function set Y(newY:int):void {
        this._Y = newY;
    }
    public function get Y():int {
        return this._Y;
    }

    public function set G(newG:int):void {
        this._G = newG;
    }
    public function get G():int {
        return this._G;
    }

    public function set H(newH:int):void {
        this._H = newH;
    }
    public function get H():int {
        return this._H;
    }

    public function set F(newF:int):void {
        this._F = newF;
    }
    public function get F():int {
        return this._F;
    }

    public function set parentNode(newParentNode:AStarNode):void {
        this._parentNode = newParentNode;
    }
    public function get parentNode():AStarNode {
        return this._parentNode;
    }

    public function setAsOrigin():void {
        _isOrigin = true;
    }
    public function checkIfOrigin():Boolean {
        return _isOrigin;
    }

    public function isThisInArray(arrayToCheck:Array):Boolean {
        for (var i in arrayToCheck) {
            if (arrayToCheck[i].X == this.X && arrayToCheck[i].Y == this.Y) {
                return true
            }
        }
        return false
    }
}
enter code here

}

2 个答案:

答案 0 :(得分:1)

快速浏览一下代码会提出错误启发式的想法。您的G值在节点中始终为0,至少我看不到它可以更改的位置。但是,在A-star算法中,您的任务(找到有障碍物的最短路径)应该代表已经到达小区的步数。这将允许算法用较短的路径替换长路径。

答案 1 :(得分:0)

有一次我编写了一个A星'算法',我使用了一个二维数组作为网格(就像你一样)。在搜索开始时,每个网格位置的“搜索”属性都设置为false。每个网格位置也有一个连接方向阵列;玩家可以选择进入的选项 - 有些可能是开放的,有些可能被封锁且无法访问 我会通过检查起始网格位置来查看它有多少方向选项来开始搜索。对于每个选项,我会将'path'数组推入_paths数组。每个'path'数组最终都会包含一系列'move'(0表示up,1表示right,2表示down,3表示left)。因此,对于每个初始路径,我会推进相应的开始移动。我还将网格位置的“搜索”属性设置为true 然后我会遍历每条路径,运行这一系列的移动以到达最近添加的位置。我会检查该位置是否是目标位置。如果不是,我会将该位置标记为已搜索,然后检查可用的方向,忽略已搜索过的位置。如果非可用,则路径将被关闭并从路径数组中“拼接” 否则,为每个可用的移动选项制作当前路径数组的ByteArray“深拷贝”,超过第一个移动选项。在一个方向上的移动被添加到当前路径和新路径中,在它们各自的方向上 如果路径数达到0,则两个位置之间没有路径。 我认为这是关于它的。我希望这对你有所帮助 请注意,搜索不需要“定向”到目标;我建议搜索所有可能的路径,然后“发生”通过杀死尝试检查已经搜索过的位置的路径来找到最直接的路径(意味着其他路径首先到达那里,因此更短)。