Actionscript 3 A-star实现,未找到最短路径问题

Actionscript 3 A-star实现,未找到最短路径问题,actionscript-3,shortest-path,a-star,Actionscript 3,Shortest Path,A Star,我的代码应该是找到从A点到B点的最短路径。为了做到这一点,我使用了A星变体。我使用二维数组来表示二维网格,但我的路径不采用对角快捷方式,只采用左、右、上和下。到目前为止,一切都很好,只是它并不总是找到可能的最短路径。我想知道出了什么问题,为什么出了问题,以及我如何解决它。先谢谢你 下面是一张图片来说明到底发生了什么: 下面是我的代码(首先是路径查找类,然后是它的助手类): 顺便说一句:Math vector只不过是一个几何点类,playerTileLocation和enemyTileLocat

我的代码应该是找到从A点到B点的最短路径。为了做到这一点,我使用了A星变体。我使用二维数组来表示二维网格,但我的路径不采用对角快捷方式,只采用左、右、上和下。到目前为止,一切都很好,只是它并不总是找到可能的最短路径。我想知道出了什么问题,为什么出了问题,以及我如何解决它。先谢谢你

下面是一张图片来说明到底发生了什么:

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

顺便说一句:Math vector只不过是一个几何点类,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;
                            }
                        }
                    }
                }
            }
        }
    }
}
}


}

快速浏览一下您的代码,就会发现错误的启发式方法。在一个节点中,你的G值总是0,至少我看不出它会在哪里变化。但是,在任务的A-star算法中(找到有障碍物的最短路径),它应该表示到达单元的步骤数。这将允许算法用较短的路径替换较长的路径。

有一次我编写了一个星型“算法”,我使用了一个二维数组作为网格(正如您所做的)。在搜索开始时,每个网格位置的“searched”属性都设置为false。每个网格位置还将有一组连接方向;玩家可以选择进入的选项-一些可能已打开,一些可能已被阻止且无法访问。
我将通过检查起始网格位置来开始搜索,查看它有多少方向选项。对于每个选项,我将把一个“path”数组推到一个_paths数组中。每个“路径”数组将包含一系列“移动”(0表示向上,1表示向右,2表示向下,3表示向左)。因此,对于每个初始路径,我将推动相应的起始移动。我还将网格位置的“搜索”属性设置为true。
然后,我将遍历每条路径,运行该移动序列以到达最近添加的位置。我会检查那个位置是否是目标位置。如果没有,我会将该位置标记为已搜索,然后检查哪些方向可用,忽略已搜索的位置。如果不可用,路径将被关闭并从路径数组中“拼接”。
否则,ByteArray会为每个可用移动选项创建当前路径数组的“深度副本”,超过第一个移动选项。在当前路径和新路径各自的方向上添加了一个方向的移动。
如果路径数曾经达到0,则这两个位置之间没有路径。 我想就是这样。我希望这会有帮助。

注意,搜索不需要“定向”到目标;我所建议的搜索所有可能的路径,只是“碰巧”通过杀死那些试图检查已经搜索过的位置的路径来找到最直接的路径(意味着其他路径先到了那里,因此更短)。

哇,我完全忘记了A-star的那部分,我现在知道它为什么会表现得如此奇怪了。中田早二似乎已经回答了我的问题,但这种方法也很有趣,我想知道哪种方法最快,这在路径发现方面非常重要。谢谢你的主意。
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