2012-02-16 23 views
7

Se me ha asignado la tarea de crear un solucionador de laberintos en Java. Aquí está la asignación:Creación de un algoritmo de resolución de laberintos en 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 

El carácter 'X' representa una pared o una posición de bloqueo y el carácter 'O' representa una posición abierta . Puede suponer que la entrada al laberinto siempre se encuentra en la esquina inferior derecha , y la salida siempre se encuentra en la esquina superior izquierda. Su programa debe enviar su salida a un archivo. Si se encuentra una ruta, el archivo de salida debe contener la ruta. Si una ruta es no encontrada, se debe enviar un mensaje al archivo. Tenga en cuenta que un laberinto puede tener más de una ruta de solución, pero en este ejercicio solo se le pedirá que busque una solución, no todas las soluciones.

Su programa debe usar una pila para registrar la ruta que está explorando y retroceder cuando alcanza una posición bloqueada.

Asegúrese de escribir un algoritmo completo antes de escribir su código. No dude en crear cualquier clase adicional de que lo ayude a completar la tarea.

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 

De todos modos, lo que he creado es una clase de puntos que ha establecido/métodos para viajar en todas las direcciones cardinales que devolverán booleanos como se muestra:

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 Estoy teniendo problemas para resolver el problema en general. Esto es lo que tengo:

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

Además de cualquier error de sintaxis, ¿podrían ayudarme? Muchas gracias.

+0

Qué error específico que se Encountering? – templatetypedef

+0

¿Podría describir los problemas que está teniendo? ¿De qué manera crees que esto no es correcto? –

+0

Bueno, no estoy seguro si estoy haciendo el vecino real revisando correctamente, como iterar por el laberinto – Copernikush

Respuesta

7

Probablemente deberías module tu programa - como puedo entenderlo, estás leyendo el laberinto del archivo y tratando de resolverlo al mismo tiempo.

Un mejor enfoque será el de dividir el programa en 2 partes diferenciadas:

  1. leer el archivo de entrada y crear una matriz con todos los datos
  2. resolver el laberinto de la matriz dada

Hacerlo le ayudará a construir y probar cada parte por separado, lo que probablemente dará como resultado un programa mejor y más confiable.

Resolver el laberinto podría hacerse mediante un simple BFS, que es similar a lo que sugirió originalmente que su algoritmo, que es una DFS

+0

Creo que el algoritmo original es un DFS, ya que está usando una pila. Dicho esto, me gusta más la solución BFS. – templatetypedef

+0

@templatetypedef: Tiene razón, he editado y solucionado ese error. Gracias. – amit

+0

No sé lo que eso significa ... aún no hemos aprendido eso. – Copernikush

1

Como Amit ha dicho, primero debe leer todo el laberinto y almacenarlo como una Matriz 2 dimensiones. Esto te permite ver todo el laberinto sin tener que resolverlo línea por línea.

Como primero tendrá que encontrar el tamaño de la matriz, debe leer el archivo de texto en una lista de cadenas.

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

El tamaño de la lista le da el número de filas, y asumiendo que es siempre una cuadrícula, puede utilizar split(). Longitud, (recuento de espacios + 1) o contar los símbolos en cualquiera de las Cadenas para obtener el número de columnas.

La forma más fácil de almacenar los datos del mapa es con una matriz bidimensional de booleanos. Donde verdadero es un muro y falso es espacio vacío.

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

    } 

} 

Ahora que tiene los datos de los mapas almacenados en una matriz que es mucho más fácil de atravesar el mapa y haga sus selecciones, puede utilizar un algoritmo ya hecho (véase la respuesta de Amit) o ​​hacer su propio. Como esto es tarea, debes intentar pensar tu propio.

Diviértete.

0

Necesita separar su programa en dos fases. El primero es la inicialización, donde lee la descripción del laberinto y la posición inicial del jugador. Después de esto, tienes una estructura de datos para representar al tablero. El segundo es el juego real, donde debe haber 3 abstracciones:

  • El estado del jugador. En su caso, es bastante simple, su posición real en el tablero.
  • El laberinto en sí, que es el medio ambiente. Debería tener funciones que le indiquen si ha visitado una posición determinada, para marcar la posición que ha visitado, dónde está el objetivo, las siguientes celdas alcanzables, etc. ...
  • La lógica, que es el algoritmo de búsqueda.

Cualquiera de estos debería ser capaz de cambiar sin mucho cambio de los demás. Por ejemplo, se le puede pedir que mejore su algoritmo de búsqueda, o un problema donde tenga más de un objetivo. La facilidad de pasar del problema actual a uno ligeramente modificado es la medida real del diseño de un programa.

12

enter image description here

presenté una respuesta similar aquí Maze Solving Algorithm in C++.

para tener la oportunidad de resolverlo, usted debe:

  • Crear una rutina recursiva Solve() y llamarse a sí misma:
    • si primero, segundo, tercero, ... son verdaderas Solve tiene tuvo éxito en encontrar una solución
    • si primero, segundo, tercero, ...contiene una falsa, tiene que dar marcha atrás y encontrar otra manera
  • Es necesario construir un buffer de lugares que ha sido evitar bucles infinitos
    • mientras hace movimientos necesarios para mantener control sobre ella
    • cuando llegamos a un callejón sin salida, tenemos que borrar los malos movimientos
    • podemos poner en práctica lo anterior por la quema de una conjetura y retirar, si es que está mal

Aquí hay un pseudo código para la solución.

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

Intenté implementar esto utilizando el algoritmo DFS utilizando algunos conceptos de OOP Java.

Ver solución completa en mi 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(); 

}

Cuestiones relacionadas