2011-03-21 1 views
1

누군가가 내 방 검색 알고리즘으로 나를 도울 수 있는지 찾는다.
미로 해결을 위해 백 트랙킹 알고리즘을 구현하려고합니다. 나는 내가 이미 방문한 방을 암기해야만하는 곳에 머물러있다.
미로는 객실에서 구성되며 각 방에는 북쪽, 동쪽, 남쪽 및 서쪽의 4 개의면이 있습니다. 각 방은 원하는 방에 문을 두어 옆 방에 연결됩니다. 즉 북쪽에 새로운 방을 만드는 room1.createNorth(roomName)이고 새 방에는 내 방의 강의실에서 볼 수있는 것처럼 처음으로 다시 연결되는 남쪽 문이 있습니다.방문한 방을 설정하여 미로 문제를 해결하는 문제

여기 미로의 각 방을 나타내는 내 잘게 썬 방 클래스입니다. 나는 북쪽을 다루는 나의 방법과 동일한 남쪽, 서쪽 그리고 동쪽 방향을 제거했다.

public class Room { 

    private String name; 
    private Room north; 
    private Room east; 
    private Room west; 
    private Room south; 
    private boolean isExit = false; 
    private Maze maze; 

    /** 
    * @return name room 
    */ 
    public String getName() { 
     return this.name; 
    } 

    /** 
    * Sets room name 
    * 
    * @param name 
    */ 
    public void setName(String name) { 
     this.name = name; 
    } 

    /** 
    * Gets northern room if any 
    * 
    * @return pointer to northern room if any, otherwise <code>null</code> 
    */ 
    public Room getNorth() { 
     return this.north; 
    } 

    /** 
    * Sets the door to the next room to the north in that room and in the other 
    * room sets southern door as connecting back to that room 
    * 
    * @param otherRoom 
    */ 
    public void setNorth(Room otherRoom) { 
     this.north = otherRoom; 
     otherRoom.south = this; 
    } 

    /** 
    * creates a new room to the north and connects back to this room 
    * 
    * @param name 
    *   of the room 
    * @return created room 
    */ 
    public Room createNorth(String name) { 
     Room otherRoom = null; 

     // create new room in that direction ONLY if there is no room yet 
     if (this.getNorth() == null) { // get northern direction, if it's null, 
             // then it's okay to create there 
      otherRoom = new Room(); // create! 
      this.setNorth(otherRoom); // set the door 
      otherRoom.setName(name); // set the name 

     } else { // there is a room in that direction, so don't create a new 
        // room and drop a warning 
      System.out.println("There is already a room in northern direction"); 
     } 

     return otherRoom; 
    } 

    /** 
    * Asdf 
    * 
    * @return maze 
    */ 
    public Maze getMaze() { 
     return this.maze; 
    } 

    /** 
    * Set maze 
    * 
    * @param maze 
    */ 
    public void setMaze(Maze maze) { 
     this.maze = maze; 
    } 

    /** 
    * @param roomName path to this room must be found 
    */ 
    public void findPathTo(String roomName) { 
     Room soughtRoom = this.getMaze().getEntry(); 

     while (!(soughtRoom.getName().equalsIgnoreCase(roomName))) { 

//   here should be also a method such as setRoomAsVisited() 

      if (this.getWest() != null) { 
       soughtRoom = this.getWest(); 
       this.getMaze().getPaths().push(soughtRoom); 
      } 
      else if (this.getNorth() != null) { 
       soughtRoom = this.getNorth(); 
       this.getMaze().getPaths().push(soughtRoom); 
      } 
      else if (this.getEast() != null) { 
       soughtRoom = this.getEast(); 
       this.getMaze().getPaths().push(soughtRoom); 
      } 
      else if (this.getSouth() != null) { 
       soughtRoom = this.getSouth(); 
       this.getMaze().getPaths().push(soughtRoom); 
      } 
      else { 
       if (this.getMaze().getPaths().isEmpty()) { 
        break; // no more path for backtracking, exit (no solution found) 
       } 
       // dead end, go back! 
       soughtRoom = this.getMaze().getPaths().pop(); 
      } 
      System.out.println(this.getMaze().getPaths().toString()); 
     } 


    } 

    @Override 
    public String toString() { 
     return "Room name is " + this.getName(); 
    } 
} 

은 미로는 다음과 같습니다 : S는

내 미로 클래스를 시작 지점을 여기

public class Maze { 

    Room room; 

/** 
* helper collection path stack for findPathTo() method 
*/ 
private Stack<Room> paths = new Stack<Room>(); 

/** 
* @return path for exit 
*/ 
public Stack<Room> getPaths() { 
    return this.paths; 
} 

    /** 
    * Singleton method for first room in the maze which is entry room 
    * 
    * @return room if no room is created then creates new, otherwise returns 
    *   already created room 
    */ 
    public Room getEntry() { 
     if (this.room == null) { 
      this.room = new Room(); 
      return this.room; 
     } 
     return this.room; 
    } 
} 

내 메인 클래스 공용 클래스 홈페이지 {

public static void main(String[] args) { 

     Maze maze = new Maze(); 
     maze.getEntry().setName("A4"); // set first room's name A4 
     // labyrinth creation 
     maze.getEntry().createEast("B4").createNorth("B3").createWest("A3"); 
     maze.getEntry().getEast().getNorth().createNorth("B2").createWest("A2") 
       .createNorth("A1"); 
     maze.getEntry().getEast().getNorth().getNorth().createNorth("B1"); 
     maze.getEntry().getEast().getNorth().getNorth().createEast("C2") 
       .createNorth("C1").createEast("D1"); 
     maze.getEntry().getEast().createEast("C4").createEast("D4"); 
     maze.getEntry().getEast().getEast().createNorth("C3").createEast("D3") 
       .createNorth("D2").setExit(true); 

     System.out.println("=====Test findPathTo method======"); 
     maze.getEntry().setMaze(maze); // set maze instance to our entrance room 
     maze.getEntry().findPathTo("B4"); 

     System.out.println("=====End of testing findPathTo method======"); 

    } 

} 

입니다 http://i.stack.imgur.com/2KePs.jpg 문제는 내 findPathTo(roomName) 방법입니다, 어떤 f 방으로 향하는 경로. 방 D4에 들어가면 알고리즘이 "A4"에서 "B4"방으로 동쪽으로 한 번 이동하고 거기에서 무한 루프가되고 스택이 방 "B4"만으로 커집니다. 왜 그것은 예를 들어 다음 방 "B3"또는 "C4"로 이동하지 않습니까?

편집 : 각 방문 방에 들어

방향 (AN enum Direction을 저장하고 Set<Direction>에 대한 : 여기에 작업 코드

public void findPathTo(String roomName) { 

     Room soughtRoom = this.getMaze().getEntry(); 

     while (!(soughtRoom.getName().equalsIgnoreCase(roomName))) { 

      if (soughtRoom.getWest() != null && soughtRoom.getWest().isVisited != true) { 
       this.getMaze().getPaths().push(soughtRoom); 
       soughtRoom = soughtRoom.getWest(); 
       soughtRoom.isVisited = true; 

      } 
      else if (soughtRoom.getNorth() != null && soughtRoom.getNorth().isVisited != true) { 
       this.getMaze().getPaths().push(soughtRoom); 
       soughtRoom = soughtRoom.getNorth(); 
       soughtRoom.isVisited = true; 

      } 
      else if (soughtRoom.getEast() != null && soughtRoom.getEast().isVisited != true) { 
       this.getMaze().getPaths().push(soughtRoom); 
       soughtRoom = soughtRoom.getEast(); 
       soughtRoom.isVisited = true; 

      } 
      else if (soughtRoom.getSouth() != null && soughtRoom.getSouth().isVisited != true) { 
       this.getMaze().getPaths().push(soughtRoom); 
       soughtRoom = soughtRoom.getSouth(); 
       soughtRoom.isVisited = true; 

      } 
      else { 
       if (this.getMaze().getPaths().isEmpty()) { 
        System.out.println("No solutions found :("); 
        break; // no more path for backtracking, exit (no solution found) 
       } 
       // dead end, go back! 
       soughtRoom = this.getMaze().getPaths().pop(); 
      } 
      System.out.println("Path rooms: " + this.getMaze().getPaths().toString()); 
     } 
    } 
+0

방을 방문 할 때 참으로 설정 한 "방문한"부울 플래그를 추가하십시오. 역 추적 중 아직 시도하지 않은 방을 통해서만 이동합니다. –

+0

안녕하세요, 감사합니다. 나는 그것을했고 그것은 달성하기위한 가장 쉬운 방법이었다. – Skyzer

답변

1

이렇게하는 방법에는 여러 가지가 있습니다.

추적 및 역 추적이 진행되면서 각 방 객체에 "isVisited"부울 플래그를 설정하거나 설정 해제해야합니다. 이것은 미로를 단일 스레드로 검색 할 수 있다는 것을 의미합니다 (이것은 중요 할 수도 있고 중요하지 않을 수도 있음).

다른 방도는 방문한 방 목록을 유지하는 것입니다 (여기서 장점은 목록에 새 방을 "밀어 넣고"자동으로 전화를 걸기가 쉽다는 것입니다) 스택으로이 목록을 전달하십시오.

isVisible에 방 하나당 검색 해시 테이블을 사용할 수도 있습니다. 이렇게하면 목록을 검색하는 것보다 (아마도) 빠른 검색이 가능하고, 멀티 스레딩이 가능합니다 ("하나 이상의 스레드가 미로를 검색 할 수 있음" , "하나 이상의 스레드가 동일한 검색에 참여할 수 없습니다").

생각해 보지 못한 몇 가지 사항이있을 수 있지만,이 세 가지 모두 구현하기 쉽습니다.

+0

감사합니다. 내 실수 였어. 내 노트북보다 오래된 버전 인 저장소에서 코드를 복사 했어. 이제 실제로 방 객체의 스택을 반환하는 getPaths() 메서드로 maze 클래스를가집니다. 내일 추적 알고리즘을 찾아 보겠습니다. – Skyzer

0

에게 신속하고 고도로 최적화되지 않은 방법입니다 예를 들어) 이전 방에서 가져온 방향뿐만 아니라 원래 있던 방을 제거하십시오. 따라서 A4에서 B4로 이동하면 B4에서 EAST를 A4 및 WEST에서 제거합니다. 뒤를 돌아봐야 할 경우 방향을 알지 못하는 방 (길 찾기 목록이 비어 있지 않음)을 찾을 때까지 스택을 풀고 다음 방을 시도하십시오. 이 시점에서 스택이 비게되면 대상 룸을 찾지 않고 모든 가능성을 시도했습니다.

내가 말했듯이 이것은 매우 최적화되지 않았지만 작동해야합니다.

0

일부 댓글 :

코드에 사용중인 일부 기능이 누락되었습니다. maze 클래스에는 getPaths() 메소드가 없습니다. 코드를 온라인에 게시하는 경우 쉽게 컴파일하고 테스트 할 수 있는지 확인하십시오. 귀하의 경우 getPaths()는 탐색 할 수있는 가능한 경로를 저장하려고 시도하는 스택을 반환하지만 실제로 수행 할 수있는 방법은 없다는 것을 추측해야합니다.

게시하기 전에 코드를 단순화하십시오. 당신의 미로는 다소 복잡하고, 당신이 만든 미로가 그림의 미로와 일치 하는지를보기 위해 그려야 할 것입니다. 훨씬 더 단순한 미로 (2 ~ 3 개의 어쩌면)로 문제를 재현 할 수 있다면 시도해보십시오. 또한 단순화하면 문제의 위치에 대한 많은 힌트를 얻을 수 있습니다. 당신이 단순화하는 동안 문제가 갑자기 사라질 지점이 있습니다.이것은 실제 버그에 대해 많은 것을 알려줍니다.

코드에 무엇이 잘못 되었을지에 대한 아이디어 : 각 방향마다 soughtRoom을 해당 방향으로 설정하십시오. 나는 soughtRoom이 당신의 수색이 현재있는 방이라고 가정하고있다. 그런 다음 그 방을 스택에 밀어 넣습니다. 그러나 역 추적의 경우 각 지사에 이전 상태로 돌아 오는 모든 정보를 저장해야합니다. 현재 방을 처음 설정 한 다음 밀어 넣으면 이전 상태의 정보가 손실됩니다. 다른 방향으로 시도해보고 무슨 일이 일어나는 지보십시오.

+0

감사합니다. 최신 버전이 아닌 저장소에서 maze 클래스를 복사했습니다. 어쨌든 이제 getPaths() 메서드가 여기 내 코드에 있습니다. – Skyzer

관련 문제