Java-A*搜索问题

Java-A*搜索问题,java,algorithm,search,a-star,Java,Algorithm,Search,A Star,问题已解决。 我已经在一个简单的基于网格的游戏中实现了一个A*搜索算法来寻找路径。这是我第一次这样做,而且大多数时候实现都非常有效。但是,有时(尽管很少)它会在有可用路径时卡住。当然,它完全被卡住的事实使它不适合使用。我假设我的实现中缺少了一些东西 我已经找了好几天这个问题,都没有结果。我有一个快速接近的最后期限和很多事情要做,我不想浪费更多的时间试图修复这个错误 编辑:我创建此文件是为了演示此问题,这样您就可以准确地看到发生了什么。它包括标题。 编辑:获取路径方法: /** * @param

问题已解决。

我已经在一个简单的基于网格的游戏中实现了一个A*搜索算法来寻找路径。这是我第一次这样做,而且大多数时候实现都非常有效。但是,有时(尽管很少)它会在有可用路径时卡住。当然,它完全被卡住的事实使它不适合使用。我假设我的实现中缺少了一些东西

我已经找了好几天这个问题,都没有结果。我有一个快速接近的最后期限和很多事情要做,我不想浪费更多的时间试图修复这个错误

编辑:我创建此文件是为了演示此问题,这样您就可以准确地看到发生了什么。它包括标题。
编辑:获取路径方法:

/**
 * @param currentPosition - the vector the avatar currently occupies.
 * @param targetPosition - the vector the avatar is aiming to reach.
 * @param levelMap - a clip map of the level.
 * 
 * @return an {@code ArrayList} of {@link ACTIONS} that the avatar can follow to reach its destination.
 **/
public static ActionPath getPath(Vector2d currentPosition, Vector2d targetPosition, LevelMap levelMap) {
    openTiles = new ArrayList<AStarTile>();
    closedTiles = new ArrayList<AStarTile>();
    targetMet = false;

    AStarTile originTile = AStarTile.fromVector(currentPosition, levelMap.getBlockSize()),
             targetTile = AStarTile.fromVector(targetPosition, levelMap.getBlockSize()),
             currentTile = null,
             parentTile = null;

    ActionPath actionPath = new ActionPath(targetTile);

    if (originTile.equals(targetTile)) {
        targetMet = true;
        return null;
    }

    GVGLogger.logInfo("Creating path from tile " + originTile + " to tile " + targetTile + " (" + currentPosition + " to " + targetPosition + ").");

    /*
     * Start the search.
     */
    openTile(originTile);
    originTile.calculateGeneration();// The origin tile will always be generation 0.
    closeTile(originTile);

    parentTile = originTile;

    while(!targetMet) {
        for (int i = 0; i != 4; i++) {
            currentTile = parentTile.move(i);// Checks an adjacent tile - up, down, left, and right respectively

            if (levelMap.inBounds(currentTile) && levelMap.isAccessible(currentTile) && !isClosed(currentTile)) {
                if (isOpen(currentTile)) {
                    // Check to see if this path to this tile is a better one.
                    currentTile = getOpen(currentTile);

                    if (currentTile.getGeneration() > parentTile.getGeneration() + 1) {
                        // The open version's generation is higher than this version's generation - it's a better path
                        currentTile.setParentTile(parentTile);
                        currentTile.calculateGeneration();
                        currentTile.calculateFinalScore();
                    }
                }
                else {
                    currentTile.setParentTile(parentTile);
                    currentTile.setHeuristic(currentTile.distanceSquared(targetTile));
                    currentTile.calculateGeneration();
                    currentTile.calculateFinalScore();
                    openTile(currentTile);
                }
            }
        }

        if (openTiles.size() > 0) {
            parentTile = getBestOption();
            closeTile(parentTile);

            if (parentTile.equals(targetTile)) {
                targetMet = true;
            }
        }
        else {
            GVGLogger.logWarning("Target unreachable!");
            return null;
        }
    }

    //Convert the path of tiles into ACTIONS that the avatar can take to reach it.

    for (int i = 0; i != closedTiles.size(); i++) {
        Vector2i difference = getDifference(closedTiles.get(i), (i != closedTiles.size() - 1 ? closedTiles.get(i + 1) : targetTile));

        if (difference.equals(1, 0)) {
            actionPath.add(ACTIONS.ACTION_LEFT);
        }
        else if (difference.equals(-1, 0)) {
            actionPath.add(ACTIONS.ACTION_RIGHT);
        }
        else if (difference.equals(0, -1)) {
            actionPath.add(ACTIONS.ACTION_DOWN);
        }
        else if (difference.equals(0, 1)) {
            actionPath.add(ACTIONS.ACTION_UP);
        }
        else if (difference.equals(0, 0)) {
            return actionPath;
        }
        else {
            GVGLogger.logWarning("Error in path-finding - found a difference of " + difference + "!");
        }
    }
    return null;
}

private static Vector2i getDifference(AStarTile tileA, AStarTile tileB) {
    return new Vector2i(tileA.getX() - tileB.getX(), tileA.getY() - tileB.getY());
}

public static boolean targetMet() {
    return targetMet;
}

private static void openTile(AStarTile toOpen) {
    if (isClosed(toOpen)) {
        closedTiles.remove(getOpen(toOpen));
    }
    if (!isOpen(toOpen)) {
        openTiles.add(toOpen);
    }
}

private static void closeTile(AStarTile toClose) {
    if (isOpen(toClose)) {
        openTiles.remove(getOpen(toClose));
    }
    if (!isClosed(toClose)) {
        closedTiles.add(toClose);
    }
}

private static boolean isClosed(AStarTile toCheck) {
    return getClosed(toCheck) != null;
}

private static boolean isOpen(AStarTile toCheck) {
    return getOpen(toCheck) != null;
}

/**
 * @return the open tile with the lowest 'final' score.
 **/
private static AStarTile getBestOption() {
    try {
        Collections.sort(openTiles);
        return openTiles.get(0);
    }
    catch(Exception e) {
    }
    return null;
}

private static AStarTile getClosed(AStarTile t) {
    for (AStarTile p : closedTiles) {
        if (p.equals(t)) {
            return t;
        }
    }
    return null;
}

private static AStarTile getOpen(AStarTile t) {
    for (AStarTile p : openTiles) {
        if (p.equals(t)) {
            return t;
        }
    }
    return null;
}
/**
*@param currentPosition-化身当前占用的向量。
*@param targetPosition-化身目标到达的向量。
*@param levelMap-该级别的剪辑贴图。
* 
*@return一个{@code ArrayList}的{@link ACTIONS},化身可以跟随它到达目的地。
**/
公共静态操作路径getPath(Vector2d currentPosition、Vector2d targetPosition、LevelMap LevelMap){
openTiles=newarraylist();
closedTiles=newarraylist();
targetMet=假;
asartile originTile=asartile.fromVector(currentPosition,levelMap.getBlockSize()),
targetFile=asartile.fromVector(targetPosition,levelMap.getBlockSize()),
currentTile=null,
parentTile=null;
ActionPath ActionPath=新的ActionPath(targetFile);
if(原始值等于(目标值)){
targetMet=真;
返回null;
}
GVGLogger.logInfo(“创建从平铺“+originTile+”到平铺“+targetTile+”(“+currentPosition+”到“+targetPosition+”)的路径”);
/*
*开始搜索。
*/
openTile(originTile);
originTile.calculateGeneration();//原始互动程序将始终是第0代。
封闭砖(原始砖);
parentTile=原始;
而(!targetMet){
for(int i=0;i!=4;i++){
currentTile=parentTile.move(i);//分别向上、向下、向左和向右检查相邻的平铺
if(levelMap.inBounds(currentTile)和levelMap.isAccessible(currentTile)和isClosed(currentTile)){
if(等参线(当前平铺)){
//检查此磁贴的路径是否更好。
currentTile=getOpen(currentTile);
if(currentTile.getGeneration()>parentTile.getGeneration()+1){
//开放版本的生成量高于此版本的生成量-这是一条更好的路径
currentTile.setParentTile(parentTile);
currentTile.calculateGeneration();
currentTile.calculateFinalScore();
}
}
否则{
currentTile.setParentTile(parentTile);
currentTile.Set启发式(currentTile.distanceSquared(targetTile));
currentTile.calculateGeneration();
currentTile.calculateFinalScore();
openTile(当前tile);
}
}
}
如果(openTiles.size()>0){
parentTile=getBestOption();
closeTile(parentTile);
if(parentTile.equals(targetTile)){
targetMet=真;
}
}
否则{
logWarning(“无法到达目标!”);
返回null;
}
}
//将瓷砖的路径转换为化身可以达到的动作。
for(int i=0;i!=closedFiles.size();i++){
Vector2i difference=getDifference(closedTiles.get(i),(i!=closedTiles.size()-1?closedTiles.get(i+1):targetfile));
if(差等于(1,0)){
actionPath.add(ACTIONS.ACTION_左);
}
else if(差等于(-1,0)){
actionPath.add(ACTIONS.ACTION\u RIGHT);
}
else if(差等于(0,-1)){
actionPath.add(ACTIONS.ACTION\u DOWN);
}
else if(差等于(0,1)){
actionPath.add(ACTIONS.ACTION\u UP);
}
else if(差等于(0,0)){
返回操作路径;
}
否则{
GVGLogger.logWarning(“路径查找错误-发现差异“+差异+”!”);
}
}
返回null;
}
私有静态向量2i getDifference(AStarTile tileA,AStarTile tileB){
返回新的Vector2i(tileA.getX()-tileB.getX(),tileA.getY()-tileB.getY());
}
公共静态布尔targetMet(){
返回targetMet;
}
私有静态void openTile(AStarTile toOpen){
如果(已关闭(打开)){
关闭文件。移除(getOpen(toOpen));
}
如果(!isOpen(toOpen)){
openTiles.add(toOpen);
}
}
专用静态无效闭合磁贴(Asartile toClose){
if(等参(toClose)){
移除(getOpen(toClose));
}
如果(!isclose(toClose)){
关闭文件。添加(关闭);
}
}
私有静态布尔值已关闭(Asartile toCheck){
return getClosed(toCheck)!=null;
}
专用静态布尔等参线(Asartile toCheck){
返回getOpen(toCheck)!=null;
}
/**
*@返回具有最低“最终”分数的打开磁贴。
**/
私有静态AStarTile getBestOption(){
试一试{
集合。排序(openTiles);
返回openTiles.get(0);
}
捕获(例外e){
}
返回null;
}
私有静态AStarTile getClosed(AStarTile t){
对于(A部分p:闭合文件){
如果(p等于(t)){
返回t;
}
}
返回null;
}
私有静态AStarTile getOpen(AStarTile t){
对于(AsArtile p:openTiles){
如果(p等于(t)){
返回t;
}
}
返回null;
}
currentTile.getGeneration() > parentTile.getGeneration() + 1
currentTile.setHeuristic(currentTile.distanceSquared(targetTile));
    if (!closedTiles.isEmpty() && toClose.getGeneration() != lastClosed().getGeneration() + 1) {
        openTiles.remove(getOpen(toClose));
        return;
    }