.......... .S****** . . * * . . ** * . . * F . . *** . ..........i.e., state whether the maze has a solution (true in the above case), and furthermore, display the solution path through the maze:
.......... .SOOOOOO . . * O . . ** O . . * F . . *** . ..........We would also like — for debugging purposes as well as general curiosity — like to follow the progress of the maze-solving algorithm:
.......... .......... .......... .......... .......... .......... .......... .S****** . .O****** . .SO***** . .S*O**** . .S**O*** . .S****** . .S****** . . * * . . * * . . * * . . * * . . * * . . O * . . * * . . ** * . . ** * . . ** * . . ** * . . ** * . . ** * . . *O * . . * F . . * F . . * F . . * F . . * F . . * F . . * F . . *** . . *** . . *** . . *** . . *** . . *** . . *** . .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .S****** . .S****** . .S****** . .S****** . .S****** . .S***O** . .S****O* . . * * . . * * . . * * . . * * . . * * . . * * . . * * . . ** * . . ** * . . ** * . . ** * . . O* * . . ** * . . ** * . . O F . . * F . . * F . . * F . . * F . . * F . . * F . . *** . . **O . . *O* . . O** . . *** . . *** . . *** . .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .S*****O . .S****** . .S****** . .S****** . . * * . . * O . . * * . . * * . . ** * . . ** * . . ** O . . ** * . . * F . . * F . . * F . . * O . . *** . . *** . . *** . . *** . .......... .......... .......... ..........We will break down this task into several preliminary subtasks leading up to the actual solving of the maze and then presenting the solution path. But first we will introduce two-dimensional arrays, which we will use to represent the maze itself.
int [][] 2DArr; double [][][] 3DMatrix;
new int[3][2];
columns 0 1 ----------- 0 | | | ----------- rows 1 | | | ----------- 2 | | | -----------
0 1 2 --------------- 0 | | | | --------------- rows 1 | | ----------- 2 | | | -----------Our lab has no need for these, and we will not address them any further.
columns 0 1 ----------- 0 | 10 | 20 | ----------- rows 1 | 30 | 40 | ----------- 2 | 50 | 60 | -----------
2DArr[0][1]
is 20
2DArr[1][0]
is 30
for (int i = 0; i < 2DArr.length; i++) for (int j = 0; j < 2DArr[i].length; j++) …
2DArr[i].length
; i.e., the rows length is the terminating condition
of the inner loop (though in the case of a rectangular array, the length of all the rows is the same).
Maze
Class: Representing, Reading, toString
.......... .S****** . . * * . . ** * . . * F . . *** . ..........Here is a table of the various characters used in the representation:
. | border |
(blank) | wall |
* | path |
S | start |
F | finish |
String
array.
static final
variables in the
class for these characters, e.g. START = 'S'
, etc
Maze
ClassMaze
that has the following instance variables:
char
array,
startRow
and startCol
.
static
read
method that follows the same logic as the other read
methods we have been writing:
char [][] array
), create a Maze
object and return it
char [][]
array, assigns the refeence to the instace variable, then iterates (traverses) the array looking for the
Start location and assigning it row/col co-ordinates to the startRow
and startCol
instance variables.
toString
method that constructs the String
representation of the maze; i.e, the representation shown above (but
without the need for the header).
12
in this case).
7 x 10 .......... .S****** . . * * . . ** * . . * F . . *** . ..........
nextInt
, the visual representation is best read in using nextLine
.
As we've discussed in class, these two methods do not interact well. To avoid any issues, please do a dummy nextLine
right after reading inthe header, i.e.:
int rows = scanner.nextInt(); scanner.next(); // skips the 'x' int cols = scanner.nextInt(); nextLine(); // positions to the next linethat will get everything in 'synch' and enable you to perform the
nextLine
for reading the visual rep.
7 x 10 .......... .S****** . . * * . . ** * . . * F . . *** . ..........
import java.util.*; import java.io.*; class MazeApp { public static void main(String [] args) throws Exception { Maze maze = Maze.read(new Scanner(new File(args[0]))); System.out.println(maze); } }
.......... .S****** . . * * . . ** * . . * F . . *** . ..........
false
(not visited); whenever you
land (visit) at a location in the maze, set the corresponding visited array location to true
visited
— a 2-D boolean array of the same size as the 2-D char
instance variable holding the maze.
false
.
boolean
-returning method that accepts the current row and column value of the current location;
the algorithm will recurse on these two parameters in the manner described above:
solve()
, that sets up the recursive parameters, and calls the recursive method.
Conceptually speaking, before we move to a new position (i.e., make a recursive call in that direction), we should make sure
it's not a wall or border. However, the logic is a bit simpler if we first 'move' to that location and if it's an invalid position
we immediately return false.
boolean solve(row, col) {…}
currentRow
and currentCol
to your class — they will represent the current position in
the maze during the solution (think of a mouse running the maze; the current position represents the mouse's position).
toString
method to include the current location. To achieve,add another character
(I used capital O) to represent the current position, and add logic to toString
print that character when you are at the current position.
.......... .......... .......... .......... .......... .......... .......... .S****** . .O****** . .SO***** . .S*O**** . .S**O*** . .S****** . .S****** . . * * . . * * . . * * . . * * . . * * . . O * . . * * . . ** * . . ** * . . ** * . . ** * . . ** * . . ** * . . *O * . . * F . . * F . . * F . . * F . . * F . . * F . . * F . . *** . . *** . . *** . . *** . . *** . . *** . . *** . .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .S****** . .S****** . .S****** . .S****** . .S****** . .S***O** . .S****O* . . * * . . * * . . * * . . * * . . * * . . * * . . * * . . ** * . . ** * . . ** * . . ** * . . O* * . . ** * . . ** * . . O F . . * F . . * F . . * F . . * F . . * F . . * F . . *** . . **O . . *O* . . O** . . *** . . *** . . *** . .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... .S*****O . .S****** . .S****** . .S****** . . * * . . * O . . * * . . * * . . ** * . . ** * . . ** O . . ** * . . * F . . * F . . * F . . * O . . *** . . *** . . *** . . *** . .......... .......... .......... ..........
solutionPath
, of the same dimensions as the maze,
initialized to false
.
true
.
getSolutionPath
that displays the maze just like toString
but
uses a different chaaracter (my O above) for any location that is true in the SolutionPath
array.