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