2015-04-24 2 views
0

Я пытаюсь использовать Stack (Depth First Search), чтобы решить лабиринт. У меня есть несколько вопросов, кроме основной проблемы, которая в настоящее время я получаю бесконечный цикл, когда мой стек становится пустым. У меня есть хорошее понимание того, что мне нужно делать. У меня просто возникают проблемы с его применением к моему коду.Бесконечная петля, когда мой стек пуст

Я следую этому алгоритму для решения лабиринтов:

1.Create пустых стек

2.Search массив для исходного местоположения.

3.Place отправной точкой на стек

4.Remove точку из стека

5.Test, чтобы увидеть, если эта точка является отделка (если она есть, конец цикла)

6.Otherwise, отметить место в лабиринте, как оценивается, чтобы показать тракт

7.Проверьте пятна в лабиринте, которые являются соседними с текущим местоположением (вверх, вниз, влево, вправо).

8.Если они не являются стенами и еще не были оценены, добавьте эти точки в стек, чтобы определить другие местоположения.

Решить метод с методами Helper (большинство ошибок в solveDFS())

//Tries going up,down,left,or right from current location and 
    //marks path if valid. The algorithm should finish when reaching 
    //the finish spot 
    public static boolean solveDFS(char [][] maze){ 
    LinkedStack stack = new LinkedStack(); 
    Point startLoc = findPoint(maze,'s'); 
    Point finishLoc = findPoint(maze, 'f'); 
    stack.push(startLoc); 

    Point[] neighborSpots = getNeighborSpots(startLoc); 

    boolean test = true; 
    while (test){ 
     stack.pop(); 
     if(stack.peek().equals(finishLoc)){ 
      printMaze(maze); 
      test = false; 
      return true; 
     }else{ 
      for(Point evaluate : neighborSpots){ 
       if(validSpot(stack, maze)){ 
        placeMarker(stack, maze); 
        if(stack.peek().equals(evaluate)){ 
         return true; 
        } 
        removeMarker(stack, maze); 
       } 
      } 
     } 
    } 
    return false; 
} 
//Returns true of coordinates of free spot is valid or finish spot 
//Should not be off edge of maze 
private static boolean validSpot(LinkedStack spot, char [][] maze){ 
    if (spot.peek().x < 0 || spot.peek().x >= maze.length || 
      spot.peek().y < 0 || spot.peek().y >= maze[spot.peek().x].length) { 
     return false; 
    } 
    return (maze[spot.peek().x][spot.peek().y] == ' ' || maze[spot.peek().x][spot.peek().y] == 'f'); 
} 
//Searches the array for a point 
private static Point findPoint(char [][] maze, char c) { 
    for (int i = 0; i < maze.length; i++) { 
     for (int j = 0; j < maze[i].length; j++) { 
      if (maze[i][j] == c) { 
       return new Point(i, j); 
      } 
     } 
    } 
    return null; 
} 
//returns an array containing coordinates of neighbor spots 
private static Point[] getNeighborSpots(Point spot) { 
    Point[] neighborSpots = new Point[4]; 

    neighborSpots[0] = new Point(spot.x + 1, spot.y); 
    neighborSpots[1] = new Point(spot.x, spot.y + 1); 
    neighborSpots[2] = new Point(spot.x - 1, spot.y); 
    neighborSpots[3] = new Point(spot.x, spot.y - 1); 

    return neighborSpots; 
} 
//Marks the path by adding a '.' 
private static void placeMarker(LinkedStack spot, char [][] maze){ 
    maze[spot.peek().x][spot.peek().y] = '.'; 
} 
//Removes marker from path by adding a blank space 
private static void removeMarker (LinkedStack spot, char [][] maze) { 
    maze[spot.peek().x][spot.peek().x] = ' '; 
} 
+0

Почему бы не использовать стек программ вместо использования собственного? – Bhoot

+0

@Bhoot Извините, может быть, я должен был уточнить, что это для задания, которое я должен использовать самостоятельно. – JCCS

+0

Кажется, что отсутствует часть, я не вижу никакого толчка, кроме начального местоположения – Vyncent

ответ

0

Вы не можете выскочить из или заглядывать в верхней части пустого стека. Поэтому для реализации стека должен быть предикат (метод boolean isEmpty()) для проверки того, пуст ли пуст. Код, который заглядывает в стек или появляется из стека, должен использовать этот предикат и обрабатывать случай с пустым стеком как особый случай или должен быть написан таким образом, чтобы гарантировать, что он никогда не манипулирует пустым стеком. Последнее на практике сложнее и реже.

Но что должен делать метод pop или peep из стека, если он is вызвал пустой стек? То есть, если метод был вызван с ошибкой? Метод должен сигнализировать об ошибке, бросая подходящее исключенное исключение. Это облегчит отладку ошибки. Является ли стек пустым, является частью информации о состоянии, если стек. Таким образом, стек находится в состоянии, которое недопустимо для метода pop или peek. Таким образом, наиболее подходящим является IllegalStateException.

+0

Я заметил это, и, похоже, это то, что вызывает мой бесконечный цикл. Любая идея, что я должен делать? – JCCS

+0

См. Также http://stackoverflow.com/a/7390181/545127 – Raedwald

1

Ваш цикл изменяет переменную цикла (test) к ложным, если вы найти путь (но эффект не имеет никакого значения, потому что вы можете вернуться из метода.

Ваш цикл не имеет и не изменить переменную цикла в других случаях . Установите test ложь, если все пути сделаны, и никто не будет успешным.

Или просто не проверить логическую переменную, но пустота стека в вашем выражении петли (while (!stack.isEmpty())).

+0

Спасибо, это решило проблему с бесконечным циклом. Теперь я предполагаю, что остальное - логические ошибки, потому что мой стек всегда пуст. – JCCS

0

3.Place начальный точка на стек

4.Удалить точку из стека

Уверены ли вы, что это действительно хорошая идея?

0

Я попытался исправить логические ошибки в вашем коде. Следующий код должен работать, но он не поместит ваши маркеры по желанию:

public static boolean solveDFS(char [][] maze){ 
    LinkedStack stack = new LinkedStack(); 
    Point startLoc = findPoint(maze,'s'); 
    Point finishLoc = findPoint(maze, 'f'); 
    stack.push(startLoc); 
    while (!stack.isEmpty()) { 
     Point curr = stack.pop(); 
     if(curr.equals(finishLoc)) { 
      printMaze(maze); 
      return true; 
     } else { 
      Point[] neighborSpots = getNeighborSpots(curr); 
      for(Point evaluate: neighborSpots) { 
       if(validSpot(stack, maze)) { 
        placeMarker(stack, maze); 
        stack.push(evaluate); 
        removeMarker(stack, maze); 
       } 
      } 
     } 
    } 
    return false; 
} 
+0

Я вижу изменения и пытаюсь понять их, и они кажутся логичными, но я получаю ту же проблему, что она никогда не соответствует условию if. Мой стек кажется пустым, поскольку это сообщение, которое я получаю от своего класса LinkedStack, и лабиринт не распечатывается. – JCCS

+0

Можете ли вы вставить весь код (включая LinkedStack и Point class) на ideone и вставить ссылку здесь? – Bhoot

+0

Это главная: https://ideone.com/g9BmZE Это LinkedStack: https://ideone.com/riu7kA Это узел: https://ideone.com/WSvdZo Я решил начать с нуля и использовать некоторые алгоритмы, которые я нашел здесь, так что это отличается от того, что было, но у меня все еще есть проблемы. В настоящее время вы получаете IndexOutOfBoundsException. Также у меня нет класса Points. Я использую библиотеку Java. – JCCS

Смежные вопросы