Maze Project
Maze Project
In this project …
…You will write a program accomplishing two major tasks:
Generate a random two-dimensional maze. The Maze will be created on a grid of Cells of various kinds and will be
rendered in a graphical UI (GUI). It will be semantically correct: fills the entire grid, doesn’t isolate unreachable areas,
includes one entry and one exit location, includes some “no-trespass” blocks and guarantees the existence of a path from
the entry to the exit.
Solve the randomly generated maze. You will design and implement the algorithm that determines automatically
the path from the entry to the exit. The algorithm will render its path exploration in the GUI.
Checkpoints
the
Specification and
The complete project specification can be broken down into the following sections: To reach project completeness, the development effort is divided into the
following checkpoints:
Checkpoint 1:
Maze class. Practicing with MazeCanvas.
Object Model Algorithms UI design UML Diagram API Reference
Checkpoint 2:
When complete, your project includes a full implementation of the following classes: Cell classes: Cell, ShadedCell, EdgeCell.
Initialize the Maze.
Program.java:
Main class of the project. Implements the main() method for creating, generating and solving a Maze.
Maze.java: Checkpoint 3:
Cell classes: Adding BlockCell, EntryCell,
Implements the Maze as the container for the grid of Cells and for the entrance and exit cells. ExitCell to the Maze.
Implements the maze initialization code.
Cell.java:
Implements the core state and behaviors common to all type of cells. Checkpoint 4:
Generator class: Implement the building
ShadedCell.java: blocks and the algorithm for generating the
Extends Cell with the ability shade the cell in a custom color. maze.
EdgeCell.java and BlockCell.java: Checkpoint 5:
Extend ShadedCell with the specific custom color for the edge or the light-gray shade for the block Solver class: Implement the building blocks
cell. These cells include the ability to prevent stepping outside the maze’s edges or stepping in or out and the algorithm for solving the maze.
of a block cell.
EntryCell.java and ExitCell.java:
Extend EdgeCell with the specific custom entry and exit shade colors. Used to identify the entrance
Final 6:
Explorer class: Refactor Generator and
into and exit from the maze. Solver as extensions of Explorer.
Explorer.java:
Implements the depth-first, recursive exploration algorithm. Provides default implementation for
helper methods called internally from within this algorithm.
Generator.java and Solver.java:
Extend Explorer overriding some of its methods in order to generate the maze in a consistent and
complete manner, or to solve it by finding a path from the entrance to the exit.
the Maze project
A Maze is a two-dimensional grid of nRows x nCols cells. Each Cell is a square space which
may be surrounded by walls on any of its Top, Left, Right or Bottom sides. Some Cells may EdgeCell Maze
have a specific shade (background) color. These are ShadedCells. There are several kinds is a ShadedCell
is a Cell A nRows x nCols two-dimensional grid
of such cells: of Cells of various kinds. Contains a
pink shade, walls on their outer sides. special EntryCell and ExitCell.
EdgeCell: These are the cells at the edge of the Maze: first and last row and first and
last column. Their shade is of a specific edgeColor (your choice) different than the
default white. They have walls on their outer sides, but they may or may not have walls 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
on their inner sides. For instance, all EdgeCells on the first row have a wall on their Top ExitCell 1
side while the ones on last column have a wall on their Right side. The EdgeCell from is an EdgeCell
2
is a ShadedCell
the bottom right corner of the maze has walls on its Right and Bottom sides. is a Cell 3 EntryCell
is an EdgeCell
BlockCell: There are few such cells inside the maze: less than 5% of their total number. EdgeCell of green shade, 4 is a ShadedCell
marks the maze exit is a Cell
These cells have walls on all their sides and have a light gray shade. They represent 5
impassable areas, like a block of concrete covering its entire cell. 6 EdgeCell of blue
shade, marks the
7 maze entrance
EntryCell: This is a special kind of EdgeCell: There is only one such cell, representing
8
the entrance in the maze. It has a shade of a distinct color (your choice), different than
9
the edge shade or the default white.
10
ExitCell: This is yet another special kind of EdgeCell: There is only one such cell, 11
representing the exit from the maze. Its shade is distinct from all the other shade
colors in the maze.
Cell BlockCell
is a ShadedCell
The size of the maze (nRows and nCols) and the various shade colors are your choice. The Interior to the maze, no is a Cell
maze shown on the right is only giving an example of such choices. shade (default – white),
may or may not have walls Light gray shade, walls on
on any of its sides. all their sides, impassable.
Generating the maze Step into the cell from its Left side Solve further by exploring the Top side
As the generating algorithm progresses, each step forward is rendered as a path
connecting the current cell to the next one. The path is rendered in a color of your
choice. You can see below some examples of how the UI reflects the progress of the
generating algorithm:
drawPath(.. Side.Left, Color.RED) drawPath(.. Side.Top, Color.RED)
Step into the cell from its Bottom side Generate further by exploring the Right side drawPath(.. Side.Center, Color.RED)
Each time a step forward is no longer possible, and the algorithm backtracks to the
previous cell, the path connecting that cell to the current one is retained but
drawPath(..Side.Bottom..) drawPath(..Side.Right..)
drawPath(..Side.Center..)
rendered in a different color of your choice.
Each time a step forward is no longer possible, and the algorithm backtracks to the No path via the Bottom side,
No path via Top, solve further
previous cell, the path connecting that cell to the current one is erased. by exploring the Bottom side return to the previous cell.
erasePath(..Side.Right..) erasePath(..Side.Top)
drawPath(..Side.Top..) erasePath(..Side.Center..)
erasePath(..Side.Bottom..)
EntryCell ExitCell
_entryShadeColor _exitShadeColor
The EdgeCell is an extension of a ShadedCell. It contains a color of • Add a ShadedCell(MazeCanvas mazeCanvas, int row, int col, Color shadeColor)
EdgeCell constructor to the class. After calling its super() with the parameters it needs, use the
choice, used for shading cells bordering the maze. It also keeps track of mazeCanvas and the shadeColor to draw the shade of this cell. Save the shadeColor
_edges[]
the edges of the cells bordering the maze such that they can be removed parameter in the corresponding class field.
_edgeColor
from the list of walls returned by the cell’s getWalls() accessor. This will
getWalls() be needed later, when implementing the exploration algorithms.
Add an EdgeCell class as an extension of ShadedCell. It contains a listOfEdges as a data
Determining the edge sides of this cell is as field and an edgeColor constant set to a color of your choice.
EdgeCell(mazeCanvas, row, col)
.. simple as testing the row and column for 0 and
for the size of the grid (given by the • Add an EdgeCell(MazeCanvas mazeCanvas, int row, int col) constructor to the class. It
if first row then calls its super() with the same parameters, plus the chosen edgeColor. In addition, it
add Side.Top to listOfEdges mazeCanvas). These edges need to be removed uses the mazeCanvas, row and col to determine the maze edges for this cell and add
else if last row then
add Side.Bottom to listOfEdges
from the list of walls of this cell, as shown in them to the listOfEdges data field.
endIf the pseudo-code below: • Override the getWalls() method from the Cell class and have it remove the maze edges
getWalls() walls
(available in the listOfEdges) from the list of walls it returns.
if first col then
add Side.Left to listOfEdges walls = super.getWalls()
else if last col then for each edge in listOfEdges do
add Side.Right to listOfEdges remove edge from walls
endIf endFor Verify all MazeCheckpoint2a.java tests are passing.
return walls
Ref: classes UML diagram :
Checkpoint 2b: initialize the Maze.
Think Code
Having the Cell and EdgeCell classes, the Maze class now needs to define a grid of cells as a class In the Maze class:
data field. There are two steps in this process: • Add a new gridOfCells data field of type Cell[][].
1. Creating the grid means creating a new two- • In the Maze(MazeCanvas mazeCanvas) constructor create a two-dimensional array of
Maze Cell dimensional array of type Cell[][] and save it in the Cells sized to the number of rows and columns of the mazeCanvas parameter. Save
_mazeCanvas
class data field. Its number of rows and columns are the array in the gridOfCells class data field.
_grid[][]
ShadedCell given by the size of the MazeCanvas instance, which • Add a new method initialize(). It takes no parameters and returns no value. In it,
getRows(), getCols() is already a data field in the Maze class. implement the algorithm described on the left to fill in the gridOfCells with the
getCell(), initialize() correct Cell instances.
Creating the grid can be implemented inside the
EdgeCell Maze class constructor. • Add a new method getCell(int row, int col). It takes a row and column location as
parameter and returns the Cell instance at that location. This method is going to be
needed later.
2. Initializing the grid means creating a new instance of type Cell for each of the locations in
the grid. If the location is on the edge, then the actual instance is of type EdgeCell
otherwise is a regular Cell. The polymorphic capability of Java allows for both to be “seen”
as Cell objects since EdgeCell is-a ShadedCell which is-a Cell.
This can be implemented as part of a new initialize() method of the Maze class. The In the Program class, in the main() method you should already have a Maze instance
pseudo-code for this method looks like below: created and used for calling into its genSnake() method. This was done as part of
Checkpoint 1.
Maze.initialize() Notice that Cell and EdgeCell instances are drawing
for each [row, col] in the grid themselves on the maze canvas when they are • Replace the call to genSnake() with a call to its new initialize() method.
do created. This means that once the maze
if [row, col] is on edge then
grid[row,col] new initialization is complete, the canvas will
EdgeCell automatically be filled with a drawing like below:
else Run and verify the program. You should see a drawing like the one on the left.
grid[row,col] new Cell
endIf
endFor Verify all MazeCheckpoint2b.java tests are passing.
Notice that unlike the genSnake() method from before,
now the Maze class is no longer in charge of doing any
drawing. It is delegating this task to the various Cell
objects which will draw themselves based on their
specific type. From the Maze point of view, they are all
abstracted out as Cells.
The simplest way to incorporate BlockCells in it is to modify the initialize() method as follows: Verify all MazeCheckpoint3a.java tests are passing.
When a random value is <= 0.05 and the count BlockCells generated so far is less than 5% of the
count of interior Cells, add to the grid a new BlockCell instead of a regular Cell and update the
count tracking their number. This is shown in the pseudo code below:
Think Code
Cell
There are two more kinds of cells that need to be implemented: The cell Add an EntryCell class and an ExitCell class to the project, as an extension of the
modeling the entrance and exit from the maze. These are the EntryCell ShadedCell EdgeCell, each containing an entryShadeColor and exitShadeColor class constants, set to a
and the ExitCell. There’s only one instance of each, located on the edge color of your choice, different than all the other.
of the maze, so these classes are natural extensions of the EdgeCell. • Add class constructors EntryCell(MazeCanvas mazeCanvas, int row, int col) and
Each has a different shade, which is also different than any other EntryCell(MazeCanvas mazeCanvas, int row, int col). After the call to super() use the
EdgeCell BlockCell mazeCanvas to change the shade of the cells to their respective colors.
shade used already (edge or block).
This checkpoint is all about coding these building blocks. Verify all MazeCheckpoint4a.java tests are passing.
Checkpoint 4b: the Generator algorithm.
Think Code
This checkpoint is about completing the maze generating logic which is implemented in the run() In the Program class, in the main() method you should already have a maze instance of
method of the Generator class. Its client code is wired in the main() method of the Program class: class Maze and a mazeCanvas instance of MazeCanvas. They were created as part of
Checkpoint 1. You should also have a call to maze.initialize() method, done as part of
To do its job, the generator instance Program.main() Checkpoint 2b.c
needs the Maze instance holding all the create new mazeCanvas instance • Create a generator instance of the class Generator, right after the line initializing the
data of the maze, and the MazeCanvas create new maze instance mazeCanvas maze. Pass the maze and mazeCanvas instances as its parameters.
instance needed for rendering the open mazeCanvas
initialize maze • Call the generator’s run() method right after the generator initialization.
progress of the generating logic. Those
create new generator mazeCanvas, You can add a call to mazeCanvas.breakLeap() after these two lines such that the
are provided in the Generator class
maze execution is suspended once the maze is generated and before the program terminates.
constructor.
generator.run()
close mazeCanvas
Two more methods need to be In the Generator class, add a generatePathColor class constant defining the color of the
implemented in the Generator class: run() exploration path shown during maze generation. Set it to a color of your choice.
and run(cell, fromSide). run() is the starting point, calling the run(cell, fromSide)
with the entryCell of the maze, available through maze’s • Implement the run(Cell cell, Side fromSide) method from the pseudo code.
getEntryCell() method, and Side.Center as the first • Use generatePathColor when drawing the path components inside the cell.
Generate.run()
direction of movement. This is akin to: You can add one or more mazeCanvas.breakStep(millis) calls inside the method such that
Generate.run(
maze.getEntryCell(),
“you just got parachuted in middle of the EntryCell”. you can visualize the progression of the algorithm in a step-by-step manner.
Side.Center)
Generate.run(cell, fromSide)
mark cell as visited
draw in cell path fromSide and If everything was implemented
Side.Center correctly, at this point you are
The run(cell, fromSide) pseudo code,
remove cell’s wall fromSide able to generate mazes and
shown to the right, implements the
get and shuffle the cell’s list of trace the algorithm progression
recursive algorithm for generating the walls like in these images:
maze. foreach side in the list of walls do
get neighbor from that side
Notice the highlighted code lines. They if neighbor is not visited then
are using the mazeCanvas class field in draw in cell path to side
order to draw the path into the cell, remove cell’s wall on that side Run and verify the program. Trace the execution by pressing the ‘S’ key and
showing the steps to and back from each Generate.run(neighbor, observe the recursive and backtracking steps of the exploration.
opposite(side))
neighboring cells. When the cell Generate mazes of different sizes using different shades and path colors.
erase cell path to side
exploration is complete, the path going endIf
through it is erased. endForeach Verify all MazeCheckpoint4b.java tests are passing.
erase Side.Center and path fromSide
Checkpoint 5a: the Solver class building blocks.
Think Code
So far, the maze contains an Entry and an Exit cell, is initialized and generated. This checkpoint is In the Cell class:
all about implementing the algorithm for finding the path from the EntryCell to the ExitCell. • Add a getPaths() method taking no parameters and returning the listOfPaths available
from this cell. These are all the cell’s Sides not bordered by a wall. Start with a new list
Similar to the generator “engine”, the solving logic containing all four sides, then remove from it all the wall sides of the cell. These are
can be coded in a new Solver class. An instance of Solver.run(cell, fromSide) available in the cell’s listOfWalls. The method returns the resulting list.
mark cell as visited
this class - the solver - needs only a reference to if cell is the Exit then
the maze and to the mazeCanvas used for return true
drawing the progress. The pseudo code for this endIf In the EdgeCell class:
get and shuffle the cell’s list of
algorithm is shown to the right: • Overload the getPaths() method such that it removes the listOfEdges from the
paths
foreach side in list of paths do listOfPaths returned by super.getPaths(). This is needed because an EdgeCell does not
Following the pattern of the Generator class, the get neighbor from that side have walls on the sides edging the maze, but those openings are not to be considered
if neighbor is not visited then part of the possible paths out of the cell.
Solver class implements the solving logic through
Solve.run(neighbor,
the run() and run(cell, fromSide) methods. opposite(side))
if maze is solved then Add a new Solver class to the project containing a mazeCanvas and a maze as class fields.
Solver.run() return true
This is the engine solving the maze by stepping from one cell to the other, starting from the
mark all cells as not visited endIf
Solve.run(maze.getEntryCell(), endIf EntryCell, until the ExitCell is reached..
Side.Center) endForeach
• Add a Solver(MazeCanvas mc, Maze m) constructor and save the parameters in the
return false
class fields.
The first run() method is the starting point, calling the second one with the maze’s EntryCell as the Add a run(Cell cell, Side fromSide) method, returning a boolean. For now, let it return
•
starting location and the Side.Center as the initial direction of movement. This is akin to: false. It is going to be needed in the next checkpoint.
“You’re parachuted in the center of the EntryCell. Find your way to the ExitCell starting from here”.
• Add a run() method returning a boolean. In it, in a loop, reset the visited state to false
for all the maze‘s cells. Then, call the overloaded run method passing to it the EntryCell
Most of the building blocks for implementing this algorithm have been put in place when the maze of the maze and Side.Center and it returns its result.
was generated, only a few more need to be coded. The complete list is as follows:
• Copy the shuffle() and getOpposite() methods from the Generator class into the
Track the cell visited state: available via Cell’s getVisited(), setVisited() methods. Solver class.
Get the cell’s neighbor on a given side: available via Maze’s getNeighbor() method. Notice: copying code is generally to be avoided. The generating and solving algorithms will
Get the opposite of a given side: available in Generator’s getOpposite() method. be refactored later in a generic maze exploration algorithm, eliminating this redundancy.
Get the list of possible paths from a given cell: these are sides of a cell without a wall. This
method fits in the Cell class, with some special handling (overload) in the EdgeCell. class.
Reset the visited marker across for all cells: when the maze was generated, all cells were
marked as visited. Solving involves tracking their visited state again, so, before starting the Verify all MazeCheckpoint5a.java tests are passing.
exploration again it needs to be reset to not_visited.
Checkpoint 5b: the Solving algorithm.
Think Code
This checkpoint is about completing the maze solving logic which is implemented in the run() In the Program class, in the main() method you should already have a maze, mazeCanvas
method of the Solver class. Its client code is wired in the main() method of the Program class. and a generator instances used to initialize and generate the maze (done as part of
Checkpoints 2b and 4b).
Program.main() So far, the client code creates and opens a
create new mazeCanvas instance mazeCanvas, creates and initializes a maze object, • Create a solver instance of the class Solver, after generator.run() call which is
create new maze instance generating the maze. Pass the maze and mazeCanvas instances as its parameters.
mazeCanvas then creates a generator object and calls its run()
open mazeCanvas method to generate the maze. • Call the solver’s run() method (the overloaded one taking no parameters) right after.
initialize maze You can add a call to mazeCanvas.breakLeap() after these two lines such that the
create new generator mazeCanvas, To solve the maze, the client code only needs to execution pauses once the maze is solved and before the program terminates.
maze create a solver object and call its run() method as
generator.run()
create new solver mazeCanvas, maze
shown to the left.
solver.run() In the Solver class, add a fwdPathColor and a bktPathColor class constants defining the
The algorithm solving the maze is implemented
close mazeCanvas color of the forward and backgrack exploration paths as shown in the pseudocode on the
in
the overloaded run(cell, fromSide) method of the Solver class: given a cell and the side that cell left. Set them to two different colors of your choice.
was entered, the algorithm needs to identify • Implement the run(Cell cell, Side fromSide) method from the pseudo code.
Solver.run(cell, fromSide)
all possible “next steps” from that location. mark cell as visited • Use fwdPathColor when drawing the path components when stepping inside a cell, or
Those are governed by a few simple rules: draw fwdPath fromSide and Side.Center forward, to a neighboring cell.
Can only go to a neighboring cell to if cell is the exit then
• Use bktPathColor when the recursive call didn’t result in a solution, such that the
return true
which a path exists (no wall on that side). explored part of the maze remains visible.
endIf
Can only go to a cell which has not been get and shuffle the cell’s list of You can add one or more mazeCanvas.breakStep(millis) calls inside the method such that
visited before. paths you can trace the progression of the algorithm in a step-by-step manner.
foreach side in list of paths do
A valid next step is attempted. If that doesn’t get neighbor from that side
lead to the ExitCell, another step is tried if neighbor is not visited then
until either a path is found (return true) or draw fwdPath to side If everything was implemented
all next steps were explored unsuccessfully Solve.run(neighbor, correctly, at this point you are able to
(return false). When taking a next step, the opposite(side)) solve mazes and trace the exploration
algorithm runs again, recursively, on the if maze is solved then
logic like in this image:
neighboring cell. return true
endIf
Entering a cell and exploring a next step, is draw bktPath from side
drawn as a “forward path”, in some color. endIf
Coming back after exploring a next step is a endForeach Run and verify the program.
draw bktPath for Side.Center and
fromSide
“backtrack path”, drawn in a different color, unless that path led to the ExitCell. Verify all MazeCheckpoint5b.java tests are passing.
return false
Final 6a: refactor Generator and Solver. The Explorer class. A callback method is just an informal name given to a normal
method which is called from other parts of the code when
certain well-defined event or conditions occur.
Think Code
For this checkpoint, review your implementations for generating and solving the maze. Notice how In each of the Generator and Solver class add the following callback protected methods:
similar they are. In both cases, there are different actions taken when a cell is entered, when • onEnterCell(Cell cell, Side side) - takes as parameters the cell being entered and the
determining the next possible steps, when stepping forward, stepping back and when exiting. side where it is entered from.
Other than that, the algorithms gluing these actions are identical. • onGetNextSteps(Cell cell) – takes as parameter the cell being inspected for the next
Let’s refactor the code by creating and calling these methods in each of the Generator and Solver maze generation step. Method returns the resulting list of walls in the Generator’s case,
classes. and the list of paths in the Solver’s case.
Generator/Solver.run(cell, fromSide) • onStepForward(Cell cell, Side side) – takes as parameters the cell and its side where
mark cell as visited the maze generating algorithm should step further.
done onEnterCell(cell, fromSide) onStepBack(boolean done, Cell cell, Side side) : takes as parameter a cell and the side
•
list of paths onGetNextSteps(cell) that was just explored. It also takes the boolean done, telling if the exploration is
foreach side in list of paths do complete or not (in Generator’s case always false; in Solver’s case, true if a path to the
if not done then exit was found, and false otherwise).
get neighbor from that side
if neighbor is not visited then • onExitCell(boolean done, Cell cell, Side side) : takes same parameters a cell and the
onStepForward(cell, side)
side on which the cell is about to be exited. It also takes the Boolean done, telling if the
exploration is complete.
done Explorer.run(neighbor,
opposite(side)) In each of these methods, copy the code parts from the corresponding
onStepBack(done, cell, side) run(Cell cell, Side side) method of their classes, as described on the left side of this slide.
endIf
endIf
endForeach
onExitCell(done, cell, fromSide);
return done In the Solver class modify the run(Cell cell, Side side) method by replacing all code parts
copied into the new methods, with the corresponding method calls and implementing the
pseudo code on this slide.
Generator Solver
Draws the cell’s path fromSide. Returns false Draw the cell’s path fromSide. Returns true
since there is no “exit” during maze if the cell is the exit from the maze. In the Generator class modify both the run() and the run(Cell cell, Side side) method by
generating process (all maze needs exploring) copying over the same methods from the Solver class.
Returns the cell’s list of paths, shuffled.
Returns the cell’s list of walls, shuffled. Draw the cell’s path side leading out to the At this point, the project is functionally unchanged, but the Generator and Solver classes
Draws the cell’s path side leading out and next cell that has not been explored yet. contain a fair amount of identical code. This is going to be factored out next, into a new
removes the wall separating it from next cell. Explorer class.
If not done, draws the path side coming
Erases the path side coming back into the cell. back into the cell, in a distinct color.
Erases the path fromSide, leaving the cell. If not done, draws the path leaving the cell, Verify all MazeCheckpoint6a.java tests are passing.
in a distinct color.
Final 6b: refactor Generator and Solver. The Explorer class.
Think Code
Add an Explorer class to the project, having maze, mazeCanvas, fwdPathColor and
The Generator and Solver classes are now restructured in a way that highlights their common state bktPathColor as protected class fields. In it:
(fields) and behavior (methods):
• Add a constructor Explorer(MazeCanvas mc, Maze m, Color fwdColor, Color bktColor)
initializing the class fields from the given parameters.
Explorer Both classes contain a reference to the maze and mazeCanvas
_mazeCanvas and a fwdPathColor marking the path forward as the • Copy the shuffle() and getOpposite() methods from either the Generator or Solver and
change their accessibility from private to protected.
_maze exploration process advances.
_fwdPathColor, _bktPathColor The Solver class contains a bktPathColor constant for marking • Copy both the run() and run(Cell cell, Side fromSide) methods from either the
the path backtracking when the exploration cannot continue. Generator or Solver since their implementation is identical in both.
getOpposite()
shuffle() Both classes contain identical implementations for shuffle(),
getOpposite(), run() and recursive run() methods. Add the callback methods to the Explorer class as protected methods:
onEnterCell()
onGetNextSteps() Both classes contain implementations for the callback • onEnterCell(Cell cell, Side side) – draws the side path and center of the cell. In
onStepForward() methods onEnterCell(), onGetNextSteps(), onStepForward(), fwdPathColor (if color is not null). Returns false.
onStepBack() onStepBack() and onExitCell() which are very similar one to • onGetNextSteps(Cell cell) – returns a new and empty List<Side>.
onExitCell() the other. • onStepForward(Cell cell, Side side) – draws the side path of the cell, in fwdPathColor.
run()
This commonality can be extracted into one class, the • onStepBack(boolean done, Cell cell, Side side) – if not done, either draws or erases the
side path of the cell, depending on whether bktPathColor is set to a non-null value.
Explorer, working at a higher level of abstraction:
• onExitCell(boolean done, Cell cell, Side side) – if not done, either draws or erases the
Given a mazeCanvas, a maze and optionally a side path and center of the cell, depending on whether bktPathColor is not null.
Generator Solver fwdPathColor and a bktPathColor an Explorer
instance navigates through all the cells of the maze Make the Generator and Solver classes extensions of the Explorer class, delete their class
onEnterCell() onEnterCell() fields (now encapsulated in their super class) and modify their methods as follows:
drawing the progress forward and the steps
onGetNextSteps() onGetNextSteps()
onStepForward() backwards as needed. Exploration completes when • Delete shuffle() and getOpposite() and both run() methods from each class.
all cells have been visited. • Delete onStepBack() and onExitCell() methods from the Generator class.
With this class designed for such a generic exploration task, the Solver and Generator become • Delete onStepForward(), onStepBack() and onExitCell() methods from the Solver class.
very simple extensions of the Explorer, overriding only some of the callback methods, as needed: • Modify constructors and callback methods by leveraging their super() implementations.
Using the MazeCanvas class you can draw or erase any of the four walls of a cell or set
the cell’s shade to a color of your choice. You can also draw or erase a path through the
cell by connecting its center to any of the four edges.
Shade Wall
lightYellow Side.Top
Center
darkRed The side of the wall
being erased.
MazeCanvas
• edu.ftdev.DrawingFactory