2015-09-27 46 views
2

所以我正在編寫一個程序,生成並解決迷宮。除了這個小東西外,我已經做好了一切工作。迷宮中的標記將完成迷宮的第二步到最後一步,然後停下來,然後移動到不同的方向。我一直在爲此工作了大約2個小時,跟蹤我的代碼,似乎無法找到最後一步走向哪裏或爲何變得古怪。迷宮程序無法完成

迷宮的規則是X是牆壁,不能移動,O是可以移動的區域,.是起點。 -是我已經轉移到的路徑。標記可以以任何順序或主要方向(北,東北等)移動。

我有兩個矩陣,一個叫mat,向用戶顯示XO-'s。我還有另一個叫做visited的矩陣,其大小與mat相同,並且是跟蹤我可以或不可以移動到的座標的幕後矩陣。它爲牆壁存儲W,我已經訪問過的座標爲Y,我可以訪問的座標爲N

我解決迷宮的方法是檢查可能的移動從北部開始,逆時針繞指南針移動,直到找到可能的移動。標記不能移動以發現它已經移動。

如果遇到有多個可能移動的分割路徑,我將該位置的座標放在兩個堆棧中,分別稱爲splitx,列爲splity,然後我可以稍後再回來。如果我遇到了每個方格都是牆壁或已經訪問過的死角,我會回溯到分割路徑堆棧中的最後一個座標,關閉剛剛移動到的路徑,並彈出堆棧的最高值。

我還有另一個堆棧,名爲visitStack,它存儲我爲北方的每個移動N,東北的NE,等等。這讓我回顧我的動作,並轉到我遇到的最後一條分割路徑。這裏是代碼和它下面的一些選擇輸出。如果您對代碼或輸出有任何疑問或者只是一般性的澄清,請離開。

import java.util.*; 

public class MazeLab 
{ 
    public static void main(String args[]) 
    { 
     Scanner input = new Scanner(System.in); 
     System.out.print("Enter random starting seed ===>> "); 
     int seed = input.nextInt(); 

     Maze maze = new Maze(seed); 
     maze.displayMaze(); 
     maze.solveMaze(); 
    } 
} 

class Maze 
{ 

    private char mat[][];    // 2d character array that stores the maze display 
    private char visited[][];   // 2d character array that works behind to scenes to let me know where I can or can't move 
    private Stack<String> visitStack;   // stack that stores every move I make as N, NE, E, SE, etc 
    private int nowR, nowC;      // coordinates for current position in the matrix 
    private int startRow, startCol;    // coordinates for the starting position 
    private boolean done = false;    // not that important 
    private Stack<Integer> splitx = new Stack<Integer>(); // row coord for split paths 
    private Stack<Integer> splity = new Stack<Integer>(); // col coord for split paths 
    Random random = new Random(); 

    public Maze(int seed) 
    // constructor which generates the random maze, random starting location 
    // and initializes Maze class values. If the random value equals 0 the maze 
    // store an 'X' otherwise it store an 'O' in the maze. 
    { 
     Random randomize = new Random(seed); 
     mat = new char[12][12]; 
     visited = new char[12][12]; 
     for (int r = 0; r < 12; r++) 
      for (int c = 0; c < 12; c++) 
      { 
       if (r == 0 || c == 0 || r == 11 || c == 11) 
        mat[r][c] = 'X'; 
       else 
       { 
        int rndInt = randomize.nextInt(2); 
        if (rndInt == 0) 
         mat[r][c] = 'X'; 
        else 
         mat[r][c] = 'O'; 
       } 
      } 
     mat[0][0] = 'O'; 
     startRow = randomize.nextInt(12); 
     startCol = 11; 
     nowR = startRow; 
     nowC = startCol; 
     mat[startRow][startCol] = '.'; 
     visitStack = new Stack<String>(); 

     for(int i = 0; i < mat.length; i++) 
      for(int k = 0; k < mat[i].length; k++) 
       if(mat[i][k] == 'X') 
        visited[i][k] = 'W'; 
       else 
        visited[i][k] = 'N'; 
//          Avoid going back to the starting point 
     visited[nowR][nowC] = 'Y'; 
    } 


    void displayMaze() 
    // displays the current maze configuration 
    { 
     for (int r = 0; r < 12; r++) 
     { 
      for (int c = 0; c < 12; c++) 
       System.out.print(mat[r][c] + " "); 
      System.out.println(); 
     } 
     System.out.println(); 

     if(done == false) 
      pause(); 
    } 


    public void solveMaze() 
    { 
    // for testing purposes, this is not the real method 
     for(int i = 0; i < 15; i++) 
     { 
      getMove(); 
      displayMaze(); 
     } 
    } 

    private int numMoves() 
    // This method determines if a position has a valid move or not  
    { 
     int moves = 0; 
     if(nowR != 0 && visited[nowR-1][nowC] == 'N') 
      moves++; 
     if(nowR != 0 && nowC != 11 && visited[nowR-1][nowC+1] == 'N') 
      moves++; 
     if(nowC != 11 && visited[nowR][nowC+1] == 'N') 
      moves++; 
     if(nowR != 11 && nowC != 11 && visited[nowR+1][nowC+1] == 'N') 
      moves++; 
     if(nowR != 11 && visited[nowR+1][nowC] == 'N') 
      moves++; 
     if(nowR != 11 && nowC != 0 && visited[nowR+1][nowC-1] == 'N') 
      moves++; 
     if(nowC != 0 && visited[nowR][nowC-1] == 'N') 
      moves++; 
     if(nowR != 0 && nowC != 0 && visited[nowR-1][nowC-1] == 'N') 
      moves++; 
     return moves; 
    } 

    private void getMove() 
    { 
     if(numMoves() > 1) 
     { 
//          checks for split paths 
//          north 
      if(nowR != 0 && visited[nowR-1][nowC] == 'N') 
      { 
       splitx.push(nowR); 
       splity.push(nowC); 
      } 
//          northwest 
      if(nowR != 0 && nowC != 0 && visited[nowR-1][nowC-1] == 'N') 
      { 
       splitx.push(nowR); 
       splity.push(nowC); 
      } 
//          west 
      if(nowC != 0 && visited[nowR][nowC-1] == 'N') 
      { 
       splitx.push(nowR); 
       splity.push(nowC); 
      } 
//          southwest 
      if(nowR != 11 && nowC != 0 && visited[nowR+1][nowC-1] == 'N') 
      { 
       splitx.push(nowR); 
       splity.push(nowC); 
      } 
//          south 
      if(nowR != 11 && visited[nowR+1][nowC] == 'N') 
      { 
       splitx.push(nowR); 
       splity.push(nowC); 
      } 
//          southeast 
      if(nowR != 11 && nowC != 11 && visited[nowR+1][nowC+1] == 'N') 
      { 
       splitx.push(nowR); 
       splity.push(nowC); 
      } 
//          east 
      if(nowC != 11 && visited[nowR][nowC+1] == 'N') 
      { 
       splitx.push(nowR); 
       splity.push(nowC); 
      } 
//          northeast 
      if(nowR != 0 && nowC != 11 && visited[nowR-1][nowC+1] == 'N') 
      { 
       splitx.push(nowR); 
       splity.push(nowC); 
      } 
     } 
     if(numMoves() > 0) 
     { 
//          moves the marker, oriented to the right 
//          north 
      if(nowR != 0 && visited[nowR-1][nowC] == 'N') 
      { 
       nowR--; 
       visited[nowR][nowC] = 'Y'; 
       visitStack.push("N"); 
       mat[nowR][nowC] = '-'; 
//    System.out.println("PUSHING ON NORTH"); 
      } 
//          northwest 
      else if(nowR != 0 && nowC != 0 && visited[nowR-1][nowC-1] == 'N') 
      { 
       nowR--; 
       nowC--; 
       visited[nowR][nowC] = 'Y'; 
       visitStack.push("NW"); 
       mat[nowR][nowC] = '-'; 
//    System.out.println("PUSHING ON NORTHWEST"); 
      } 
//          west 
      else if(nowC != 0 && visited[nowR][nowC-1] == 'N') 
      { 
       nowC--; 
       visited[nowR][nowC] = 'Y'; 
       visitStack.push("W"); 
       mat[nowR][nowC] = '-'; 
//    System.out.println("PUSHING ON WEST"); 
      } 
//          southwest 
      else if(nowR != 11 && nowC != 0 && visited[nowR+1][nowC-1] == 'N') 
      { 
       nowR++; 
       nowC--; 
       visited[nowR][nowC] = 'Y'; 
       visitStack.push("SW"); 
       mat[nowR][nowC] = '-'; 
//    System.out.println("PUSHING ON SOUTHWEST"); 
      } 
//          south 
      else if(nowR != 11 && visited[nowR+1][nowC] == 'N') 
      { 
       nowR++; 
       visited[nowR][nowC] = 'Y'; 
       visitStack.push("S"); 
       mat[nowR][nowC] = '-'; 
//    System.out.println("PUSHING ON SOUTH"); 
      } 
//          southeast 
      else if(nowR != 11 && nowC != 11 && visited[nowR+1][nowC+1] == 'N') 
      { 
       nowR++; 
       nowC++; 
       visited[nowR][nowC] = 'Y'; 
       visitStack.push("SE"); 
       mat[nowR][nowC] = '-'; 
//    System.out.println("PUSHING ON SOUTHEAST"); 
      } 
//          east 
      else if(nowC != 11 && visited[nowR][nowC+1] == 'N') 
      { 
       nowC++; 
       visited[nowR][nowC] = 'Y'; 
       visitStack.push("E"); 
       mat[nowR][nowC] = '-'; 
//    System.out.println("PUSHING ON EAST"); 
      } 
//          northeast 
      else if(nowR != 0 && nowC != 11 && visited[nowR-1][nowC+1] == 'N') 
      { 
       nowR--; 
       nowC++; 
       visited[nowR][nowC] = 'Y'; 
       visitStack.push("NE"); 
       mat[nowR][nowC] = '-'; 
//    System.out.println("PUSHING ON NORTHEAST"); 
      } 
     } 
     if(numMoves() == 0) 
     { 
      while(nowR != splitx.peek() && nowC != splity.peek()) 
      { 
       switch(visitStack.pop()) 
       { 
//         have to backtrack the opposite direction i previously went 
        case "N": visited[nowR][nowC] = 'N'; 
           mat[nowR][nowC] = 'O'; 
           nowR++; 
           break; 
        case "NE": visited[nowR][nowC] = 'N'; 
           mat[nowR][nowC] = 'O'; 
           nowR++; 
           nowC--; 
           break; 
        case "E": visited[nowR][nowC] = 'N'; 
           mat[nowR][nowC] = 'O'; 
           nowC--; 
           break; 
        case "SE": visited[nowR][nowC] = 'N'; 
           mat[nowR][nowC] = 'O'; 
           nowR--; 
           nowC--; 
           break; 
        case "S": visited[nowR][nowC] = 'N'; 
           mat[nowR][nowC] = 'O'; 
           nowR--; 
           break; 
        case "SW": visited[nowR][nowC] = 'N'; 
           mat[nowR][nowC] = 'O'; 
           nowR--; 
           nowC++; 
           break; 
        case "W": visited[nowR][nowC] = 'N'; 
           mat[nowR][nowC] = 'O'; 
           nowC++; 
           break; 
        case "NW": visited[nowR][nowC] = 'N'; 
           mat[nowR][nowC] = 'O'; 
           nowR++; 
           nowC++; 
           break; 
        default: System.out.println("SOMETHING WENT WRONG WITH BACKTRACKING"); 
       } 
      } 
//          blocks off dead ends 
//          north 
      if(nowR != 0 && visited[nowR-1][nowC] == 'N') 
       visited[nowR-1][nowC] = 'Y'; 
//          northwest 
      else if(nowR != 0 && nowC != 0 && visited[nowR-1][nowC-1] == 'N') 
       visited[nowR-1][nowC-1] = 'Y'; 
//          west 
      else if(nowC != 0 && visited[nowR][nowC-1] == 'N') 
       visited[nowR][nowC-1] = 'Y'; 
//          southwest 
      else if(nowR != 11 && nowC != 0 && visited[nowR+1][nowC-1] == 'N') 
       visited[nowR+1][nowC-1] = 'Y'; 
//          south 
      else if(nowR != 11 && visited[nowR+1][nowC] == 'N') 
       visited[nowR+1][nowC] = 'Y'; 
//          southeast 
      else if(nowR != 11 && nowC != 11 && visited[nowR+1][nowC+1] == 'N') 
       visited[nowR+1][nowC+1] = 'Y'; 
//          east 
      else if(nowC != 11 && visited[nowR][nowC+1] == 'N') 
       visited[nowR][nowC+1] = 'Y'; 
//          northeast 
      else if(nowR != 0 && nowC != 11 && visited[nowR-1][nowC+1] == 'N') 
       visited[nowR-1][nowC+1] = 'Y'; 

      splitx.pop(); 
      splity.pop(); 
     } 
    } 

    private void pause() 
    { 
     Scanner input = new Scanner(System.in); 
     String dummy; 
     System.out.print("\nPress <Enter> to continue ===>> ");      
     dummy = input.nextLine();        
    } 
} 

這是標記移動通過它之前的迷宮。 enter image description here

這是最後的迷宮。注意當標記應該向西北移動完成迷宮時,它會在下一個回合中停留在同一個地方,然後在回合之後向南移動。

enter image description here

+0

您是否嘗試過調試它,單步執行代碼以查看發生了什麼? – Andreas

+0

是的,我追蹤了好幾遍,不明白爲什麼它不會在最後一步向西北方向移動。我試着在標記向西北方向移動時放置一個'System.out.println'語句,並在最後一步移動時打印它,但該點仍然是'O' –

+0

@Andreas http://i.imgur .com/4fkKYM7.png –

回答

3

所以,你在位置(1,1),並找到兩個動作:NW和S.

if(numMoves() > 1)火災和堆棧上推

if(numMoves() > 0)火災和適用NW移動,讓你在(0,0)。

if(numMoves() == 0)由於沒有從(0,0)移動,所以發生並開始回溯。

2個問題:

  • 如果是檢測你找到了退出的代碼?
  • if(numMoves() == 0)正在呼叫numMoves()使用新的座標。將其更改爲else
+0

試圖回答+1 –

+0

哇,這讓我感到無聊,只需要改變這些if語句的順序。 –

+0

而且我仍然在處理退出條件的代碼/沒有解決方案,我無法繼續處理這個錯誤。 –