2012-02-16 4 views
7

Мне поручена задача создания лабиринта в Java. Вот назначение:Создание алгоритма решения лабиринта в Java

Write an application that finds a path through a maze. 
The maze should be read from a file. A sample maze is shown below. 

O O O O O X O 
X X O X O O X 
O X O O X X X 
X X X O O X O 
X X X X O O X 
O O O O O O O 
X X O X X X O 

Символ «X» представляет стена или блокированный положение и символ «O» представляет собой открытую позицию. Вы можете предположить, что вход в лабиринт всегда находится в нижней правой руке , а выход всегда находится в верхнем левом углу. Ваша программа должна отправить свой файл в файл. Если найден путь, выходной файл должен содержать путь. Если путь не найден, файл должен быть отправлен. Обратите внимание, что в лабиринте может быть больше одного пути решения, но в этом упражнении вас попросят найти одно решение, а не все решения.

Ваша программа должна использовать стек для записи пути, который он исследует, и возврата, когда он достигает заблокированного положения.

Обязательно напишите полный алгоритм перед написанием кода. Не стесняйтесь создавать любые дополнительные классы , которые помогут вам выполнить задание.

Here's my Algorithm: 
1)Initialize array list to hold maze 
2)Read text file holding maze in format 
    o x x x x o 
    o o x o x x 
    o o o o o x 
    x x x x o o 
3)Create variables to hold numbers of columns and rows 
3)While text file has next line 
    A. Read next line 
    B. Tokenize line 
    C. Create a temporary ArrayList 
    D. While there are tokens 
     i. Get token 
     ii. create a Point 
     iii. add point to temp ArrayList 
     iv. increment maximum number of columns 
    E. Add temp to maze arraylist, increment max rows 
    F. initialize a hold of points as max rows - 1 
    G. Create a start point with x values as maximum number of rows - 1, and y values as maximum number of columns - 1 
    H. Create stack of points and push starting location 
    I. While finished searching is not done 
     i. Look at top of stack and check for finish 
     ii. check neighbors 
     iii. is there an open neighbor? 
      - if yes, update flags and push 
      - if no, pop from stack 
    J. Print solution 
4. Done is true 

Во всяком случае, то, что я создал класс очки, которые установить/получить методы для путешествий во всех основных направлениях, которые возвращают булевы, как показано ниже:

public class Points<E> 
{ 
private int xCoord; 
private int yCoord; 
private char val; 
private boolean N; 
private boolean S; 
private boolean E; 
private boolean W; 

public Points() 
{ 
    xCoord =0; 
    yCoord =0; 
    val =' '; 
    N = true; 
    S = true; 
    E = true; 
    W = true; 

} 

public Points (int X, int Y) 
{ 
     xCoord = X; 
     yCoord = Y; 

} 

public void setX(int x) 
{ 
    xCoord = x; 
} 
public void setY(int y) 
{ 
    yCoordinate = y; 
} 

public void setNorth(boolean n) 
{ 
    N = n; 
} 
public void setSouth(boolean s) 
{ 
    S= s; 
} 
public void setEast(boolean e) 
{ 
    E = e; 
} 

public void setWest(boolean w) 
{ 
    W = w; 
} 

public int getX() 
{ 
    return xCoord; 

} 

public int getY() 
{ 
    return yCoord; 
} 
public char getVal() 
{ 
    return val; 
} 

public boolean getNorth() 
{ 
    return N; 
} 
public boolean getSouth() 
{ 
    return S; 
} 

public boolean getEast() 
{ 
    return E; 
} 
public boolean getWest() 
{ 
    return W; 
} 

public String toString1() 
{ 
    String result = "(" + xCoord + ", " +yCoord + ")"; 
    return result; 
} 

}

I «У меня просто проблемы с фактическим решением в основном. Вот что у меня есть:

import java.io.*; 
import java.util.*; 
import java.lang.*; 
import java.text.*; 


public class MazeSolve1 
{ 
    public static void main(String[] args) 
    { 
//Create arrayList of Points 
ArrayList<ArrayList<Points>> MAZE = new ArrayList<ArrayList<Points>>(); 
Scanner in = new Scanner(System.in); 

//Read File in 
System.out.print("Enter the file name: "); 
String fileName = in.nextLine(); 
fileName = fileName.trim(); 
FileReader reader = new FileReader(fileName+".txt"); 
Scanner in2 = new Scanner(reader); 

//Write file out 
FileWriter writer = new FileWriter("Numbers.out"); 
PrintWriter out = new PrintWriter(writer); 
boolean done = false; 
int maxCol = 0; 
int maxRow = 0; 

while(!done) { 

    //creating array lists 
    while (in2.hasNextLine()) { 
     //Read next line 
     String nextLine = in2.nextLine(); 
     //Tokenize Line 
     StringTokenizer st = new StringTokenizer(nextLine, " "); 
     //Create temp ArrayList 
     ArrayList<ArrayList<Points>> temp = new ArrayList<ArrayList<Points>>(); 

     //While there are more tokens 
     while (st.hasNextToken()) { 
      String token = st.nextToken(); 
      Points pt = new Points(); 
      temp.add(pt); 
      maxCol++ 
     } 
     MAZE.add(temp); 
     maxRow++; 
    } 

    //create hold arraylist for max rows of maze -1 
    //create variables for start x and y coordinates 
    ArrayList<ArrayList<Points>> hold = new ArrayList<ArrayList<Points>>(); 
    hold = MAZE.get(maxRow - 1); 
    int startColumn = hold.get(maxCol - 1); 
    int startRow = hold.get(maxRow - 1); 
    Point start = new Point(); 
    start.setX(startColumn); 
    start.setY(startRow); 

    //initialize stack, and push the start position 
    MyStack<Points> st = new ArrayStack<Points>(); 
    st.push(start.toString1()); 
    //south and east of start are edges of array 
    start.setSouth(false); 
    start.setEast(false); 

    //while your position is not equal to point (0,0) [finish] 
    while (st.peek() != "(0, 0)") { 

     //getting the next coordinate to the North 
     int nextY = start.getY() - 1; 
     int nextX = start.getX(); 

     //if character to the North is an O it's open and the North flag is true 
     if (hold.get(nextY) = 'O' && start.getNorth() == true) { 
      //set flags and push coordinate 
      start.setNorth(false); 
      st.push(start.toString1()); 
     } 
     //else pop from stack 
     else { st.pop(); } 

     //look at coordinate to the East 
     nextX = start.getX() + 1; 
     //if character to the East is a O and the East flag is true 
     if (hold.get(nextX) = 'O' && start.getEast() == true) { 
      //set flags and push coordinate 
      start.setEast(false); 
      st.push(start.toString1()); 
     } 
     //else pop from stack 
     else { st.pop(); } 

     //look at coordinate to the South 
     nextY = start.getY() + 1; 
     //if character to the South is a O and the West flag is true 
     if (hold.get(nextY) = 'O' && start.getSouth() == true) { 
      //set flags and push coordinate 
      start.setSouth(false); 
      st.push(start.toString1()); 
     } 
     //else pop from stack 
     else { st.pop() } 

     //keep looping until the top of the stack reads (0, 0) 
    } 

done = true; 
} 

//Print the results 
System.out.println("---Path taken---"); 
for (int i = 0; i< st.size(); i++) { 
    System.out.println(st.pop); 
    i++ 
} 

Помимо любых синтаксических ошибок, могли бы вы, ребята, мне помочь? Большое спасибо.

+0

Какие конкретные ошибки вы встречая? – templatetypedef

+0

Не могли бы вы описать проблемы, которые у вас есть? Каким образом вы считаете, что это неверно? –

+0

Ну, я не уверен, правильно ли я выполняю фактический сосед, как итерация через лабиринт. – Copernikush

ответ

7

Возможно, у вас должна быть module ваша программа - я могу это понять, вы читаете лабиринт из файла и пытаетесь решить его одновременно.

Лучший подход будет разделить программу на 2 отдельные части:

  1. читать входной файл и создать матрицу со всеми данными
  2. решить лабиринт из данной матрицы

Это поможет вам построить и протестировать каждую деталь отдельно, что, вероятно, приведет к созданию более надежной и надежной программы.

Решение лабиринта может быть сделан путем простого BFS, который похож на то, что ваш алгоритм изначально предложил, который является DFS

+0

Я думаю, что исходный алгоритм - это DFS, так как он использует стек. Тем не менее, мне больше нравится решение BFS. – templatetypedef

+0

@templatetypedef: Вы правы, я исправил и исправил эту ошибку. Благодарю. – amit

+0

Я не знаю, что это значит ... мы еще не изучили этот материал. – Copernikush

1

Как Амит сказал, вы должны сначала прочитать весь лабиринт и хранить его в качестве 2 мерной матрицы. Это позволяет вам увидеть весь лабиринт, не решая его по очереди.

Поскольку вам нужно сначала найти размер массива, вы должны прочитать текстовый файл в списке строк.

List<String> strs = new ArrayList<String>(); 

//Pseudocode, choose however you want to read the file 
while(file_has_next_line) { 
    strs.add(get_next_line); 
} 

Размер списка дает количество строк, и предполагая, что всегда сетку, вы можете использовать раскол(). Длина (количество пробелов + 1) или подсчет символов на любом из Строки, чтобы получить количество столбцов.

Самый простой способ хранения данных карты - это 2D-массив булевых. Где истина стена, а ложь - пустое пространство.

boolean[][] wallMap = new boolean[rows][cols]; 

for(int i = 0; i < wallMap.length; i++) { 

    //Separate each symbol in corresponding line 
    String[] rowSymbols = strs.get(i).split(" "); 

    for(int j = 0; j < wallMap[i].length; j++) { 

     //Ternary operator can be used here, I'm just keeping it simple 
     if(rowSymbols[j].equals("X")) { 
      wallMap[i][j] = true; 
     } else { 
      wallMap[i][j] = false; 
     } 

    } 

} 

Теперь, когда у вас есть данные карты, хранящиеся в массиве это намного проще пройти карту и сделать свой выбор, вы можете либо использовать готовый алгоритм (см ответ Amit), или создать свой собственный. Поскольку это домашнее задание, вы должны попробовать и придумать свое.

Удачи.

0

Вам необходимо отделить свою программу в два этапа. Первая - это инициализация, где вы читаете описание лабиринта и начальную позицию игрока. После этого у вас есть структура данных для представления платы. Второй - это настоящая игра, где должны быть 3 абстракции:

  • Состояние игрока. В вашем случае это довольно просто, его фактическое положение на доске.
  • Лабиринт сам, который является окружающей средой. Он должен иметь функции, говорящие вам, если вы посетили заданную позицию, чтобы отметить позицию, которую вы посетили, где цель, ближайшие доступные ячейки и т. Д.
  • Логика, которая является алгоритмом поиска.

Любое из них должно быть в состоянии изменить без значительных изменений в других. Например, вас могут попросить улучшить алгоритм поиска или проблему, когда у вас есть несколько целей. Легкость перехода от текущей проблемы к слегка модифицированной является реальной метрикой дизайна программы.

12

enter image description here

я представил аналогичный ответ здесь Maze Solving Algorithm in C++.

Чтобы иметь возможность в решении, вы должны:

  • Создать Solve() рутина и рекурсивно вызывать себя:
    • если первый, второй, третий, ... истинны Solve имеет удалось найти решение
    • если 1, 2, 3, ...содержит ложные, он должен вернуться назад и найти другой способ
  • Вы должны создать буфер мест, где вы были, чтобы избежать бесконечных циклов
    • как вы сделаете шаги, необходимые, чтобы следить за ней
    • , когда мы попали в тупик, мы должны стереть плохие ходы
    • мы можем реализовать выше путем сжигания в догадке и удалить его, если это не так

Вот несколько псевдокодов для решения.

boolean solve(int X, int Y) 
{ 
    if (mazeSolved(X, Y)) 
    { 
     return true; 
    } 

    // Test for (X + 1, Y) 
    if (canMove(X + 1, Y)) 
    { 
     placeDude(X + 1, Y); 
     if (solve(X + 1, Y)) return true; 
     eraseDude(X + 1, Y); 
    } 

    // Repeat Test for (X - 1, Y), (X, Y - 1) and (X, Y + 1) 
    // ... 

    // Otherwise force a back track. 
    return false; 
} 
0

Я попытался реализовать это с использованием алгоритма DFS, используя некоторые концепции ООП Java.

Смотреть полное решение на мой github repository

private boolean solveDfs() { 
    Block block = stack.peekFirst(); 
    if (block == null) { 
     // stack empty and not reached the finish yet; no solution 
     return false; 
    } else if (block.equals(maze.getEnd())) { 
     // reached finish, exit the program 
     return true; 
    } else { 
     Block next = maze.getNextAisle(block); 
     // System.out.println("next:" + next); 
     if (next == null) { 
      // Dead end, chose alternate path 
      Block discard = stack.pop(); 
      discard.setInPath(false); 
      // System.out.println("Popped:" + discard); 
     } else { 
      // Traverse next block 
      next.setVisited(true); 
      next.setInPath(true); 
      stack.push(next); 
     } 
    } 
    return solveDfs(); 

}

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