2012-09-14 3 views
3

해결 : 죄송합니다. 나는 부적절하게 경로를 재구성하고 있었다. closedSet에는 처음부터 끝까지 모든 중간 지점이 있다고 생각했지만 다른 중간 지점도 있습니다. 나는 그 개념을 이해하지 못했다. 이제는 일하고있어!A-Star 나쁜 웨이 포인트를 선택하십시오.


나는 여전히 A *에 문제가 있습니다.

내 캐릭터가 경로를 찾고 있지만 때로는지도를 클릭하는 위치에 따라 알고리즘이 최단 경로 또는 경로를 찾지 만 선택하지 않아야하는 노드가 많습니다.

나는 초보자 구현을위한 위키 백과의A * 길 찾기를 수행하려고했습니다,하지만 그들은 나에게 동일한 결과를 제공합니다. 발견 적 알고리즘인지 알고리즘인지는 모르겠지만 뭔가 잘못되었습니다.

그리고이 두 개의 서로 다른 노드를 클릭 문제의 예는 다음과 같습니다

import java.util.ArrayList; 
import java.util.Collections; 
import java.util.TreeSet; 

public class Pathfind { 
public Pathfind(){ 

} 

public ArrayList<Node> findPath(Node start, Node end, ArrayList<Node> nodes){ 

    ArrayList<Node> openSet = new ArrayList<Node>(); 
    ArrayList<Node> closedSet = new ArrayList<Node>(); 

    Node current; 

    openSet.add(start); 

    while(openSet.size() > 0){ 

     current = openSet.get(0); 

     current.setH_cost(ManhattanDistance(current, end)); 

     if(start == end) return null;   
     else if(closedSet.contains(end)){ 
      System.out.println("Path found!"); 
      return closedSet; 
     } 

     openSet.remove(current); 
     closedSet.add(current); 

     for(Node n : current.getNeigbours()){   
      if(!closedSet.contains(n)){  
       if(!openSet.contains(n) || (n.getG_cost() < (current.getG_cost()+10))){ 
        n.setParent(current); 
        n.setG_cost(current.getG_cost()+10); 
        n.setH_cost(ManhattanDistance(n, end)); 

         if(!openSet.contains(n)) 
          openSet.add(n); 

        Collections.sort(openSet); 
       } 
      } 
     } 
    }  

    return null; 
} 

private int ManhattanDistance(Node start, Node end){ 
    int cost = start.getPenalty(); 

    int fromX = start.x, fromY = start.y; 
    int toX = end.x, toY = end.y; 

    return cost * (Math.abs(fromX - toX) + Math.abs(fromY - toY)); 
} 

}

+2

5 개의 if 문이 중첩되어 있습니다. 나는 bool을 반환하는 메서드를 사용하거나 조건부로 넣을 것을 권장합니다. – tehdoommarine

+0

지도에 대한 자세한 내용을 입력하십시오. 맵의 유형에 따라, 다른 거리 메트릭이 경험적으로 사용될 수도 정확하지 않을 수도 있습니다. –

+1

그냥 코멘트 -''ArrayList''로'closedSet'을 선택하는 것이 효율적이지 않다고 생각합니다. 각각의'contains()'op는'O (n)'(n은 닫힌 노드의 수)입니다. 보다 나은 성능을 위해'Set'을 사용해야합니다.'HashSet'은 현명한 선택이며, 삽입 순서를 유지하려면'LinkedHashSet'을 사용해야합니다. ('Node'의'equals()'와'hashCode()'메소드를 오버라이드해야합니다.) – amit

답변

0

당신의 단위는 상/하/좌/우를 걸어 수행 여기 http://i.imgur.com/gtgxi.jpg

는 Pathfind 클래스의 아니면 오직 대각선을 취할 수 있습니까?

는 A * -heuristic에 대한 하나 개의 요구 사항은 admissible 점입니다 - 그것은 결코 이상 -estimate 실제 경로 길이해야합니다. 유닛이 대각선으로 걸을 수 있다면 manhatten 거리가 경로 길이를 과대 추정하므로 A *가 작동하는 것이 보장되지 않습니다.

+0

그러나 경로가없는 이유는 무엇입니까? A *는 추론 할 수있는 휴리스틱 함수 없이는 여전히 * 완전 *합니다. * 최적 *이 아니므로, 가장 짧은 경로가 아니라 경로를 발견했을 것입니다. 대각선이 여전히 한 단계 (h = sqrt (2) 동안 h * = 1 인 경우)로 계산되는 것으로 가정하면 유클리드 거리는 여전히 허용되지 않습니다. – amit

+0

MY 단위가 대각선으로 이동하지 않습니다. 알고리즘, 인접 노드 및 선택한 노드 (목표)에서 선택한 경로를 보여주는 새 이미지를 업로드했습니다. – Jh62

1

나는 버그가 조건이라고 생각 : 비용 (g(node)+h(node)가) 현재에서 감소되어있는 경우가 전진 방지 안

if(n.getCost() < current.getCost()){ 

.이 카운터 예제를 보라 : (S 소스이며, T는 대상) 이제

_________ 
|S |x1|x2| 
---------- 
|x3|x4|x5| 
--------- 
|x6|x7|T | 
---------- 

, 당신은 S에있는 가정, 아직 너무 g(S) =0를 이동하고, 맨해튼 거리 휴리스틱에서하지 않은 , h(S) = 4은, 그래서 당신은 x1,x3에서 봐, 지금 f(S)=4

를 얻을 : 각 하나의 단계를 복용 가정, 그들은 g(x1)=g(x3)=1이되며, 모두 동일한 추론에서 h(x1)=h(x3)=3있을 것이다. f(x1)=f(x3)=4이 나오고 if 조건이 아무 것도 열리지 않으므로 S에서 반복을 완료하면 아무 것도 open으로 푸시하지 않고 검색이 종료됩니다. 보조 노트로


:
나는 ArrayListclosedSet의 선택이 효율적이지 않다 생각합니다. 각 op는 O(n)입니다. 여기서 n은 닫힌 노드의 수입니다.더 나은 성능을 위해 Set을 사용해야합니다. HashSet은 현명한 선택이며 삽입 순서를 유지하려면 LinkedHashSet을 사용해야합니다. (참고로 equals()hashCode() 메서드를 Node으로 바꿔야합니다.)

+0

저는 속도에 대해 걱정하지 않습니다. 이것은 단지 테스트 일뿐입니다. 먼저 작동시켜야합니다. 어쨌든 조언 주셔서 감사합니다. 나는 그것에 대해 뭔가를 읽었습니다. – Jh62

+0

@ user1656222 : 대답의 주된 문제는 여전히 있습니다. 언급 된 조건이 잘못되어 알고리즘이 실패합니다. 속도 문제는 단지 참고 사항 일 뿐이므로 지금은 무시하고 대답에 언급 된 다른 문제에만 집중할 수 있습니다. – amit