Java 一种简单的星型算法&塔防路径捕获
首先,我在一个使用Java的100级CS大学课堂上。我们的任务是做一个塔防游戏,我在路径上遇到了麻烦。我从搜索中发现A*似乎是最好的选择。虽然当我在路径上打U时,我的路径被卡住了。我将展示一些初级psuedo代码,因为我还没有学习过数据结构类,而且我的代码看起来相当混乱(正在处理这个问题) 假设我不会使用对角线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
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*算法。见: 在每次迭代中,您需要:
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;
}
}
}