In this lab, we will implement a generic version of the Queue data type within the context of searching a maze.
In Lab 4, we explored creating a maze using a stack to organize our potential spots to open. The stack allowed us to search in a depth-first search manner for possible next Cells to open. In other words, we would explore as far as possible, and backttrack if we reached a dead end in our journey, because we were search the youngest potential Cell next.
But there are other ways to search. We now want to investigate a breadth-first search approach, where the oldest potential Cell is expanded next, and do so within the context of searching rather than creating.
In this lab, you will create the necessary data structures to search a maze with breadth-first search, and compare this to a depth-first search technique.
To implement the generic version of a Queue with nodes, you should use the generic ListNode<E> class we implemented last lab.
ListNode<E>
maze.searchers
Write a class called ListQueue<E>. This will need to implement the Queue<E> interface, and have at least a ListNode<E> called front and another called back as fields.
ListQueue<E>
Queue<E>
front
back
public void add(E value)
Create a new ListNode<E> that stores the value.
value
If the queue isEmpty, then set front to this new ListNode<E>.
isEmpty
Otherwise, the current back should refer to this new ListNode<E> as its next.
next
Finally, redirect back to reference this new ListNode<E>.
public E remove()
Call the emptyCheck method. This will throw an IllegalStateException if the queue is empty.
emptyCheck
IllegalStateException
Save the value stored in front, and redirect front to point to the next ListNode<E>.
Return the value you stored.
public E element()
Return the value stored in the front ListNode<E>.
public int size()
If front is null, return 0.
null
Otherwise, return the number of ListNode<E> that are chained from the front node.
Run the ListQueueTest suite, and ensure your above methods are passing these tests.
ListQueueTest
Write a class called ArrayQueue<E>. This will need to implement the Queue<E> interface. The E[] stuff field is provided for you, you will need to add the necessary ints to track the data. I recommend starting with front and size both equal to 0.
ArrayQueue<E>
E[] stuff
int
size
If there is no more room in the stuff array, you will need to resize.
stuff
Now, you can always add the value to the back spot in the stuff array, and increment the size.
Save the value in the front index of the array.
Increment the value of front.
Decrement the value of size.
Return the item you stored.
Return the item in the front spot of the stuff array.
Return the size field.
Run the ArrayQueueTest suite, and ensure your above methods are passing these tests.
ArrayQueueTest
A Trail is another recursive data structure, similar to a ListNode. The two fields of a Trail are a Position, denoting the end of the trail, and a link to another Trail called prev, which is a record of how you arrived at the current Trail. For the first step of a Trail, the prev is left as null.
Trail
ListNode
Position
end
prev
In this step, you will use Trails to write an algorithm in the Puzzle class that solves a maze using either a Stack or a Queue. This is because the behavior of both is abstracted into a Searcher class. The Searcher class has method names like the Queue.
Trails
Puzzle
Searcher
Queue
public Trail solve(Searcher<Trail> solver)
If there is no Explorer in the maze or no goal in the maze, then return null.
Explorer
Otherwise, add a new Trail starting at the Explorer’s position onto the solver.
solver
While the solver still has potential Trails:
Cell
Maze
OPEN
VISITED
If you empty the solver and have still not found the goal, then return null.
Run the PuzzleTest suite, and ensure your above methods are passing these tests.
PuzzleTest
Create 10 mazes of size 30x30 and for each maze, record the number of visited nodes as a percentage of the total number of open spaces in the initial maze.
Use this data to compare the Stack (from your previous lab) versus Queue search strategies. Does either strategy have any clear strengths or weaknesses?