2012-02-16 8 views
7

Zostałem przydzielony do zadania tworzenia solwera labiryntu w Javie. Oto zadanie:Tworzenie algorytmu rozwiązywania labiryntów w Javie

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 

Znak „x” oznacza ściany lub pozycji zablokowanej, a znak „O” oznacza pozycji otwartej. Możesz założyć, że wejście do labiryntu znajduje się zawsze w prawym dolnym rogu, a wyjście zawsze znajduje się w lewym górnym rogu. Twój program powinien przesłać swoje dane wyjściowe do pliku . Jeśli zostanie znaleziona ścieżka, plik wyjściowy powinien zawierać ścieżkę. Jeśli ścieżka jest , nie znaleziono wiadomości, należy wysłać do pliku. Należy pamiętać, że labirynt może mieć więcej niż jedną ścieżkę rozwiązania, ale w tym ćwiczeniu poproszono tylko o znalezienie jednego rozwiązania, a nie wszystkich rozwiązań.

Twój program powinien użyć stosu, aby zapisać ścieżkę, którą odkrywa i przejść wstecz po osiągnięciu przez zablokowanej pozycji.

Pamiętaj, aby napisać pełny algorytm przed wpisaniem swojego kodu. Możesz utworzyć dodatkowe klasy , które pomogą Ci wykonać zadanie.

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 

Zresztą, co ja utworzyły jest klasą Punkty, które ustawił/dostać sposobów podróżowania we wszystkich kierunkach kardynalnych która będzie zwracać wartości logicznych, jak pokazano:

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 właśnie mam problemy z faktycznym rozwiązaniem. Oto, co mam:

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++ 
} 

Oprócz błędów składniowych, czy możecie mi zaoferować pomoc? Wielkie dzięki.

+0

Jakie konkretne błąd ty napotykając? – templatetypedef

+0

Czy mógłbyś opisać problemy, które masz? W jaki sposób (s) uważasz, że to nie jest poprawne? –

+0

Cóż, nie jestem pewien, czy robię faktycznego sąsiada sprawdzanie poprawnie, jak Iterowanie przez labirynt – Copernikush

Odpowiedz

7

Prawdopodobnie powinieneś module swój program - jak rozumiem, czytasz labirynt z pliku i próbujesz rozwiązać go w tym samym czasie.

Lepszym rozwiązaniem będzie podzielić program na 2 odrębne części:

  1. odczytać pliku wejściowego i utworzyć macierz z wszystkimi danymi
  2. rozwiązać labirynt z danej macierzy

Takie postępowanie pomoże ci zbudować i przetestować każdą część osobno, co prawdopodobnie spowoduje lepszy, bardziej niezawodny program.

Rozwiązywanie labirynt można zrobić za pomocą prostego BFS, który jest podobny do tego, co Twój algorytm pierwotnie sugerowano, który jest DFS

+0

Myślę, że oryginalny algorytm jest DFS, ponieważ używa stosu. To powiedziawszy, bardziej podoba mi się rozwiązanie BFS. – templatetypedef

+0

@templatetypedef: Masz rację, zredagowałem i naprawiłem ten błąd. dzięki. – amit

+0

Nie wiem, co to oznacza ... jeszcze się tego nie nauczyliśmy. – Copernikush

1

Jak Amit powiedział, należy najpierw przeczytać cały labirynt i zapisać go jako Dwuwymiarowa tablica. Pozwala to zobaczyć cały labirynt bez konieczności rozwiązywania go liniowo.

Ponieważ musisz najpierw znaleźć rozmiar tablicy, powinieneś przeczytać plik tekstowy na liście ciągów znaków.

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); 
} 

Wielkość listy daje liczbę wierszy, i zakładając, że zawsze siatkę, można użyć split(). Długości (liczba miejsc + 1) lub liczyć symbole na któregokolwiek z Ciągi, aby uzyskać liczbę kolumn.

Najprostszym sposobem przechowywania danych mapy jest dwuwymiarowa tablica zmiennych. Gdzie prawda jest ściana, a fałsz to pusta przestrzeń.

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; 
     } 

    } 

} 

Teraz, że masz dane mapy zapisane w tablicy jest dużo łatwiej przemierzać mapę i dokonać wyboru, można użyć algorytmu gotowe (patrz odpowiedź Amit za) lub stworzyć własną. Ponieważ jest to praca domowa, powinieneś spróbować wymyślić własną.

Baw się dobrze.

0

Musisz podzielić program na dwie fazy. Pierwszym z nich jest inicjalizacja, w której czytasz opis labiryntu i początkową pozycję gracza. Po tym masz strukturę danych do reprezentowania tablicy. Druga to prawdziwa gra, w której powinny być 3 abstrakcje:

  • Stan gracza. W twoim przypadku jest to dość proste, jego faktyczna pozycja na planszy.
  • Sam labirynt, który jest środowiskiem. Powinien mieć funkcję informującą, czy odwiedziłeś daną pozycję, oznaczyć pozycję, którą odwiedziłeś, gdzie jest cel, następne osiągalne komórki, itd ...
  • Logika, która jest algorytmem wyszukiwania.

Każda z nich powinna być w stanie zmienić bez większych zmian pozostałych. Na przykład możesz zostać poproszony o ulepszenie swojego algorytmu wyszukiwania lub problemu, w którym masz więcej niż jeden cel. Łatwość przejścia od bieżącego problemu do nieco zmodyfikowanego jest rzeczywistym miernikiem projektu programu.

12

enter image description here

złożyłam podobną odpowiedź tutaj Maze Solving Algorithm in C++.

Aby mieć szansę w rozwiązywaniu go, powinieneś:

  • Tworzenie Solve() rutyna i rekurencyjnie nazywać się:
    • jeśli 1, 2, 3, ... są prawdziwe Solve ma udało się znaleźć rozwiązanie
    • , jeśli 1., 2., 3., ...zawiera fałszywe, to musi się cofnąć i znaleźć inny sposób
  • Trzeba zbudować bufor miejsc, które byli uniknąć nieskończone pętle
    • jak sobie ruchy, których potrzebuje, aby zachować zakładki na nim
    • , kiedy uderzył w ślepy zaułek, musimy wymazać złe ruchy
    • możemy realizować powyższe poprzez spalenie w przypuszczeniu i usunięcie go, czy to źle

Oto pseudo kod dla rozwiązania.

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

Próbowałem wprowadzić to za pomocą algorytmu DFS wykorzystując niektóre koncepcje Java OOP.

Zobacz kompletne rozwiązanie na moim 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(); 

}

Powiązane problemy