Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 一种简单的星型算法&塔防路径捕获_Java_A Star - Fatal编程技术网

Java 一种简单的星型算法&塔防路径捕获

Java 一种简单的星型算法&塔防路径捕获,java,a-star,Java,A Star,首先,我在一个使用Java的100级CS大学课堂上。我们的任务是做一个塔防游戏,我在路径上遇到了麻烦。我从搜索中发现A*似乎是最好的选择。虽然当我在路径上打U时,我的路径被卡住了。我将展示一些初级psuedo代码,因为我还没有学习过数据结构类,而且我的代码看起来相当混乱(正在处理这个问题) 假设我不会使用对角线 while(Castle not reached){ new OpenList if(up, down, left, right == passable &&am

首先,我在一个使用Java的100级CS大学课堂上。我们的任务是做一个塔防游戏,我在路径上遇到了麻烦。我从搜索中发现A*似乎是最好的选择。虽然当我在路径上打U时,我的路径被卡住了。我将展示一些初级psuedo代码,因为我还没有学习过数据结构类,而且我的代码看起来相当混乱(正在处理这个问题)

假设我不会使用对角线

while(Castle not reached){
    new OpenList
    if(up, down, left, right == passable && isn't previous node){
         //Adds in alternating order to create a more diagonal like path
         Openlist.add(passable nodes)
    }
    BestPath.add(FindLeasDistancetoEnd(OpenList));
    CheckCastleReached(BestPath[Last Index]);
{

private node FindLeastDistancetoEnd(node n){
    return first node with Calculated smallest (X + Y to EndPoint)
}
我把A*去掉了(太多了,很可能是我的问题)。因此,我将父节点添加到我的节点中,并计算正确的父节点,尽管我认为这不能解决我的问题。这是我的问题的一个图像

X=无法通行(塔楼)

O=开放列表

b=关闭列表(最佳路径)

C=城堡(终点)

S=开始

OOOOXX
SbbbBX   C
OOOOXX
现在国会大厦B是我的问题所在。当塔被放置在该配置中,并且我的导航路径被重新计算时,它会被卡住。由于上一个节点被忽略,其余节点无法访问,因此不会将任何内容放入OpenList

现在把它写出来,我想我可以让B无法通过并返回轨道。。。哈哈。虽然我开始做很多我教授称之为“破解代码”的事情,我一直在添加补丁来修复问题,因为我不想抹掉我的“宝贝”,重新开始。尽管我愿意重做它,但看到我的一些代码是多么混乱和无序,我感到很困扰,我迫不及待地想获取数据结构


任何建议都将不胜感激。

正确实施A*算法。见:

在每次迭代中,您需要:

  • 将开放节点按启发式顺序排序
  • 挑选最好的
  • --检查您是否达到目标,如果达到目标,则可能终止
  • 现在将其标记为“已关闭”,因为它将从中进行充分探索
  • 从中探索所有邻居(如果尚未关闭,则添加到打开的节点映射/或列表)
  • 根据您发布的ASCII图表,还不完全清楚电路板的高度是否超过3,是否确实有一条路径,但我们假设有

    正确的A*算法不会“卡住”——当打开的列表为空时,不存在任何路径&它会终止并返回无路径
    null

    我怀疑您可能没有关闭打开的节点(这应该在您开始处理它们时完成),或者可能没有在每次迭代中处理所有打开的节点


    使用
    映射
    将有助于检查所有相邻位置的性能,无论它们位于开放集/列表还是封闭集/列表中。

    是的,数据结构将在这类问题上对您有很大帮助。我将尝试解释A*是如何工作的,然后给出一些更好的伪代码

    A*是最好的优先搜索算法。这意味着它应该猜测哪些选项是最好的,并尝试首先探索这些选项。这要求您跟踪选项列表,通常称为“前端”(如前端)。它不会跟踪到目前为止找到的路径,就像您当前的算法一样。该算法分两个阶段工作

    第一阶段

    基本上,您从起始位置开始,所有相邻位置(北、西、南和东)都在前面。然后,算法在前面找到最有希望的选项(我们称之为
    P
    ),并在此基础上进行扩展。从前面删除位置
    P
    ,但添加所有相邻位置。嗯,不是所有的邻国;只有邻居才是真正的选择。我们不能走进一座塔,我们也不想回到我们以前见过的地方。在新的战线上,选择了最有希望的选择,以此类推。当最有希望的选项是目标
    C
    时,算法停止并进入第2阶段

    通常情况下,最有希望的选择是最接近目标的选择,就像乌鸦飞一样(忽略障碍)。所以通常,它总是首先探索最接近目标的一个。这使得算法以某种直线走向目标。但是,如果该线路被某些障碍物阻挡,则不应将障碍物的位置添加到前方。它们不是可行的选择。因此,在下一轮中,前面的其他位置将被选为最佳选择,搜索将从那里继续。这就是它如何走出死胡同的方法,就像你例子中的那样。看看这幅插图,了解我的意思:前面是中空的蓝色圆点,它们在已经处于从红色到绿色阴影中的地方标记圆点,在无法通过的地方标记蓝色圆点

    在第二阶段,我们需要一些额外的信息来帮助我们找到目标时的最短返回路径。为此,我们在每个位置存储我们来自的位置。如果算法有效,我们来自的位置必然比任何其他邻居更接近
    S
    。如果你不明白我的意思,看看下面的伪代码

    第二阶段

    当城堡
    C
    被找到时,下一步就是找到回到起点的路,收集最佳路径。在第1阶段中,我们将来自的位置存储在我们探索的每个位置中。我们知道,该位置必须始终靠近
    S
    (不要忽略障碍物)。因此,第二阶段的任务非常简单:每次都沿着路线返回到我们所处的位置,并在列表中跟踪这些位置。最后,您将得到一个列表,该列表构成了从
    C
    S
    的最短路径。然后你只需要把这个列表倒过来,你就有了答案

    我将给出一些伪代码来解释它。互联网上有很多真实的代码示例(也有Java)。此伪代码假定您使用二维数组来表示栅格。另一种方法是使用节点对象,即simp
    //Phase 1
    origins = new array[gridLength][gridWidth]; //Keeps track of 'where we came from'.
    front = new Set(); //Empty set. You could use an array for this.
    front.add(all neighbours of S);
    while(true) { //This keeps on looping forever, unless it hits the "break" statement below.
        best = findBestOption(front);
        front.remove(best);
        for(neighbour in (best's neighbours)) {
            if(neighbour is not a tower and origins[neighbour x][neighbour y] == null) { //Not a tower, and not a position that we explored before.
                front.add(neighbour);
                origins[neighbour x][neighbour y] = best;
            }
        }
        if(best == S) {
            break; //Stops the loop. Ends phase 1.
        }
    }
    
    //Phase 2
    bestPath = new List(); //You should probably use Java's ArrayList class for this if you're allowed to do that. Otherwise select an array size that you know is large enough.
    currentPosition = C; //Start at the endpoint.
    bestPath.add(C);
    while(currentPosition != S) { //Until we're back at the start.
        currentPosition = origins[currentPosition.x][currentPosition.y];
        bestPath.add(currentPosition);
    }
    bestPath.reverse();
    
    findBestOption(front) {
        bestPosition = null;
        distanceOfBestPosition = Float.MAX_VALUE; //Some very high number to start with.
        for(position in front) {
            distance = Math.sqrt(position.x * position.x - C.x * C.x + position.y * position.y - C.y * C.y); //Euclidean distance (Pythagoras Theorem). This does the diagonal thing for you.
            if(distance < distanceOfBestPosition) {
                distanceOfBestPosition = distance;
                bestPosition = position;
            }
        }
    }