Professional Documents
Culture Documents
207
Many of these same authors suggest that graphics is an Constructors
important motivating tool for teaching introductory WalkerState(Location loc, Direction dir)
computer science and provide helpful programming constructs an instance with the given Location
environments for this approach (Proulx, Raab, and and Direction
Rasala, 2002). We do not advocate teaching low-level WalkerState(WalkerState state)
Java graphics in the first programming course. In the creates a new WalkerState that is a copy of
context of the maze case study, we provide the graphical state
user interface, so that students work on programs in the Accessors
context of using graphics, but do not do any graphics Location location() returns the location
programming proper. An advanced project might be to Direction direction()returns the direction
create an alternative graphics interface in the context of Direction toRight() returns the direction
the structure provided by the case study. 90 degrees to the right of the
state's direction
Alphonce and Ventura (2002) advocate the use of design
Direction toLeft() returns the direction 90
patterns in the first computer science course, an approach
degrees to the left of the state's
that fits well with our use of case studies approach in the
direction
first courses. Examples of introducing patterns into the
Direction toReverse()returns the direction 180
first year were presented at the OOPSLA02 "Killer
degrees from the state's
Examples for Design Patterns and Objects First"
direction
workshop, (Alphonce, 2002). Astrachan et al. (1998) also Location neighborTo(Direction dir)
consider design patterns an essential part of the early returns the location immediately adjacent to the
computer science curriculum, as does Proulx (2000). state's location in the given direction
Using a maze as the basis of explaining ideas in String toString() returns a string representation
Computer Science or for programming assignments is not of this state
original. A notable example of using a maze program to Modifiers
illustrate design ideas is the book by Gamma, Helm, void turnRight() changes direction 90 degrees
Johnson, and Vlissides on design patterns (1995). They to the right
use a different structure for their maze but find it a rich void turnLeft() changes direction 90 degrees
source for illustrating design patterns. We use our own to the left
maze to illustrate some design principles and patterns. void turnAround() changes direction 180 degrees
void moveForward() changes the state's location to
3 The Maze Framework the adjacent location in the
current direction
We provide a framework within which students work. void moveToward(Direction dir)
This framework provides several classes that are "black- changes the state's location to the adjacent
box" for the students. Some of these classes set up the location in the given direction
graphical user interface and need not be seen by the Since the operations of the class WalkerState and the
students at all. Others provide functionality used by the interactions with the other parts of the program can be
students, so that they need to know about the methods done completely in terms of Location and Direction
that they are expected to use, but need not know about the objects, there is no need for students to know about the
implementation of the classes providing those methods. methods for these two classes. This is a good lesson in
Some of these black-box classes may be opened for study working with objects without worrying about the details -
later in the course. This is a setup similar to the one used - taking their interactions as defined by the class given, in
by the Marine Biology Simulation case study developed
this case WalkerState and Maze.
for the College Board Advanced Placement program in
Computer Science (Brady, 2002). 3.2 The maze
3.1 Walker state The maze consists of a grid of cells which can either be
walls or open. A walker in the maze can only move into
The framework includes two low-level classes for
open cells, not walls. One open cell is designated as the
describing the position of a walker in the maze,
goal to be reached and an initial state (location and
Location and Direction. These are borrowed from the
direction) is also part of the maze specification.
College Board Marine Biology Simulation Case Study
(Brady, 2002).1 Both these classes are immutable. A third We represent the maze with the class Maze. It has
class, WalkerState, encapsulates the geometry of the methods to provide information about the maze.
two dimensional grid that forms the maze and the state of Accessors
a walker in the maze. The WalkerState class provides int numRows() returns number of rows in maze grid
the following constructors and methods: int numCols() returns number of columns in maze grid
WalkerState start() returns starting state
Location goal() returns location of goal
1 boolean isWall(Location loc)
The MBS case study code is distributed by the College
returns true if location is a wall, otherwise false
Board under the GNU General Public License, as is the
code for this maze case study.
208
The maze has no modifier methods since it cannot be provided. This and the fact that any interactive walker
changed once it has been constructed. class must implement the MazeDisplayListener
For the first few examples using the framework, the interface is a good opportunity for describing the
student only needs to know two Maze methods: isWall Observer design pattern. The MazeDisplayListener
and goal. Later the methods for getting the dimensions interface has one method:
of the maze, numRows and numCols, and the start void onMazeInput(String mazeInput)
method can be useful. responds to call by MazeDisplay to which this
listener has been added; the parameter is set to
3.3 Displaying the maze "forward," "right," "left," or "reverse" according
The mechanism for displaying the maze is black-box to the button or location clicked.
code. The only information that a student or other user Diagram 2 shows the relationship between the
needs to know about is the interface MazeDisplay that MazeDisplay and the MazeDisplayListener.
specifies the operations of a display and the interface
register
MazeDisplayListener that any maze walker that is
interactive must implement. MazeDisplay addMazeDisplayListener MazeDisplayListener
notify
There are two different maze displays that implement the object object
onMazeInput
MazeDisplay interface. The first we call the rat's view
and it provides a display as if the user were inside the Diagram 2. Listener Relationship
maze. and could see ahead up to three cells and right or
left one cell from the current cell or any of those ahead, if 4 Early Assignments
the view is not blocked by a wall. Diagram 1 shows two
examples of what can be seen, where the bottom center The student would not see the details described above
looking up is the initial position, white cells are open, before the first assignment. A programming assignment
black cells are walls and gray cells are unknown since the would be provided with the black-box and other code and
view is blocked by a wall. a brief explanation of the nature of the listener
mechanism. This need not be in any great detail, since the
mechanism is already in place.
209
• when the user enters "forward" the walker should
import java.util.Random;
move forward one location, if that location is not a public class RandomWalker
wall. {
• when the user enters "right" the walker should turn to private WalkerState myState;
private Maze myMaze;
the right without changing location private MazeDisplay myDisplay;
• when the user enters "left" the walker should turn to
the left without changing location public RandomWalker(Maze maze,
• when the user enters "reverse" the walker should turn MazeDisplay md)
{ myMaze = maze;
around without changing location myState = maze.start();
In order to complete this assignment, the student must use myDisplay = md;
methods from the WalkerState and Maze classes. myDisplay.displayState(myState);
}
There are two variations of this assignment that result in
slightly different walker behaviors. One might require public void run()
that on "right" or "left" the walker not only turn but also { Random rand = new Random();
while(!myState.location().equals(
move into the cell to that side if it is not a wall. A second myMaze.goal()))
variation might have the walker move ahead several cells { myDisplay.eraseState(myState);
to the next location that has either a wall in front or an myDisplay.markLocation(
myState.location());
open cell to the right or left. Other variations of this sort int choice = rand.nextInt(4);
of walker could also be devised. The second type of if(choice == 0)
walker does not just using conditional statements, it also { if(!myMaze.isWall
needs loops, the objective of the next set of programs. (myState.neighborTo
(myState.direction())))
{ myState.moveForward();
4.2 A random maze walker }
}
The second set of assignments involves loops. The else if(choice == 1)
simplest version is a walker that randomly chooses from myState.turnRight();
else if(choice == 2)
the actions of the interactive walker described above at myState.turnLeft();
each step. It repeats these actions until the goal of the else // choice == 3
maze is reached. We give this example to the student as a myState.turnAround();
demonstration of the while loop. The code for
myDisplay.displayState(myState);
RandomWalker is shown below. This class is not try
interactive and therefore does not use the listener model. { Thread.sleep(50);
This class calls the methods that display the current state }
of the walker and the locations that have already been catch(InterruptedException ex){}
}}}
visited. It also includes a time delay, so that the progress
of the walker can be viewed.
4.3 Classroom experience
One can get dizzy running the original MazeDriver with
this program (although it is fun to let the students do it One of the authors, Wells, has used these assignments in
this way at first). Consequently we also supply an introductory Java programming class with great
MazeDriver2 that not only includes the bird's eye view success. The interactive walker assignments were used
of the maze but also allows the user to select the rat's shortly after the students learned about if-else statements.
view, bird's eye view, or both. They found the assignment challenging, but not
overwhelming and they had the motivation to get the
A first assignment on loops asks the student to modify the walker to find their way through the maze with the
RandomWalker class so that it does not spin in place so graphical user interface. Many students came up with
much but instead moves in whatever direction was their own variations on the interactive walker.
randomly chosen, if possible. This also gets to the goal of
In the same class, students were given the assignment of
the maze considerably faster than the given version.
writing the random walker -- they were not given the first
Other variations of random walker include walkers that version of the random walker that we gave above. They
use the Direction class constants NORTH, SOUTH, EAST, found this to be an exciting assignment and immediately
WEST and walkers that keep track of where they have demanded a bird's eye view display. These students found
been, using some data structure, and do not repeat the right-hand walker to be a challenging assignment.
locations unless there was no other choice (this involves
interesting conditional logic). Another variation would 5 Design Issues
generate a list of possible moves that are not walls, then
randomly select the next location from that list. Sometime after the interactive and the "automatic"
A challenging assignment that exercises a student's ability (random and right-hand) walkers have been developed in
to use conditional logic is the right-hand (or left-hand) class and assignments, and after inheritance has been
walker. The right-hand walker moves through the maze in introduced, these can be used to demonstrate some ideas
a deterministic fashion as if keeping the right hand on the about object-oriented design and design patterns. We do
wall at all times. This algorithm will solve many, but not not advocate an emphasis on the use of design patterns in
all mazes. the first programming course, but some discussion of
210
GenericWalker <<interface>>
MazeDisplayListener
211
further into this example. A good guide for this example
is the Template design pattern that suggests a base class GenericWalker <<interface>>
implement the aspects of an algorithm that are common
MazeDisplayListener
to the prospective subclasses, and encapsulates the details
of the algorithm in abstract methods that are filled in by
the subclasses. This abstract class fits nicely into the
inheritance hierarchy.
Looking at the family of interactive walkers that were <<abstract>>
developed in the exercises, every one has a common
control structure in the onMazeInput method - they all InteractiveWalker
check the value of the parameter mazeInput and take a
different action based on its value. They all also display
the new state after taking an action. These aspects can be
drawn out in discussion with students and result in the InteractiveWalker1 InteractiveWalker2
abstract class, InteractiveWalker, a subclass of
GenericWalker, which the new versions of concrete
interactive walkers will extend, a shown in diagram 4. Diagram 4. Refinement
The code for the abstract InteractiveWalker class is public abstract class InteractiveWalker
shown below the diagram, followed by the code that extends GenericWalker
implements InteractiveWalkerStart3, functionally implements MazeDisplayListener
{
the same as InteractiveWalkerStart, as a subclass. public InteractiveWalker(Maze maze,
Each concrete interactive walker need only fill in the four MazeDisplay md)
abstract methods that specify what the walker is to do in { super(maze, md);
response to each command. Students can reimplement display.addMazeListener(this);
}
one or more of the other interactive walker variations.
public void onMazeInput(String mazeInput)
The use of the template design pattern here demonstrates {
the power of inheritance. display().eraseState(state());
212
This outline is the basis for our version of the code for the give a solution that has the correct recursive algorithm in
abstract AutoWalker. terms of recursive calls and checking for walls, but leave
out any data structure that keeps track of where you have
In this code we have used a variation that can be useful in been, thereby causing an infinite recursion. Give the
application of the template pattern. Since not every students the problem of fixing this version. This puts the
AutoWalker needs to do an initialize method or a
focus on the issue of the second rule of recursion: you
wrapup method, we have made these empty methods must make progress toward the base case (the first rule is
rather than abstract methods. In that way, those versions that you must have a base case). Depending on what data
of an automatic walker that do not need them can simply structures have been covered at this point in your course,
leave them unimplemented -- the empty version in the the following are reasonable solutions to this problem:
template will be called and will do nothing. On the other • an ArrayList of locations visited
hand, the takeStep method must be implemented by
• a Boolean two-dimensional array where true
any concrete automatic walker for it to make sense, so it
indicates the corresponding position has been visited
is an abstract class.
• a Java List or Set of locations that have been
When we look at recursive walkers we will see that we visited.
can use a similar approach to organizing our classes. We
will look at advanced iterative walkers that do depth-first 6.2 Variations on recursion
and breadth-first search as classes that extend
Students can do different variations of recursive solutions
AutoWalker.
as additional exercises. For example, they can do the
recursion based on going forward, right, left, reverse from
public abstract class AutoWalker the current state or they can use the constants from the
extends GenericWalker
{ Direction class to drive the recursion. These give
public AutoWalker(Maze maze, somewhat different behavior, although there is no reason
MazeDisplay md) to prefer one over the other. A "guided" recursion would
{ super(maze, md);
first move to locations closer to the goal.
}
213
of course the correct thing to do, as soon as the Set
public class DepthWalker0 extends AutoWalker
hierarchy has been introduced into your course. {
Stack searchStack;
Another implementation of the Maze would use a Stack visitStack;
Boolean two-dimensional array to represent the walls.
This is another exercise that can be used when two- public DepthWalker0(Maze maze,
dimensional arrays are covered in your course. MazeDisplay md)
{ super(maze, md);
Thus the Maze class provides an interesting context for }
protected void initialize()
demonstrating or making assignments on some of the { searchStack = new StackAL();
standard data structures that we cover in the first year of visitStack = new StackAL();
Computer Science: expandable arrays (ArrayList), two- searchStack.push(new
WalkerState(state()));
dimensional arrays, sets. }
protected void takeStep()
8 Data Structures { if(searchStack.isEmpty())
{ throw new IllegalStateException(
The maze framework provides some interesting "no solution");
applications of standard data structures: stacks, queues, }
setState((WalkerState)searchStack.pop());
and priority queues. By controlling an iterative search visitStack.push(state());
using these data structures we develop depth-first, if(!state().location().
breadth-first, and best-first (heuristic) searches equals(maze().goal()))
{ Location loc =
respectively. The problem of recording the moves made state().neighborTo(Direction.NORTH);
during the search and reconstructing the path provides an if(!maze().isWall(loc))
interesting application of stacks. { searchStack.push(new
WalkerState(loc, Direction.NORTH));
Since each of these searches is iterative, the classes }
implementing them can be developed as subclasses of the loc =
state().neighborTo(Direction.EAST);
AutoWalker class discussed above. Then the focus can be if(!maze().isWall(loc))
on the steps that need to be done, without regard to the { searchStack.push(new
graphics display that is taken care of in the AutoWalker WalkerState(loc, Direction.EAST));
class. }
loc =
state().neighborTo(Direction.SOUTH);
8.1 Depth-first search if(!maze().isWall(loc))
{ searchStack.push(new
We propose giving a partial solution for this class, WalkerState(loc, Direction.SOUTH));
leaving the students two parts to complete. First, we give }
loc =
a correct iterative depth-first search algorithm using a state().neighborTo(Direction.WEST);
stack for the intermediate storage structure, but without if(!maze().isWall(loc))
any means for preventing the search from repeating itself. { searchStack.push(new
The first problem is for the student to select a data WalkerState(loc, Direction.WEST));
}
structure and modify the methods so that the search does }
not loop endlessly, but eventually moves to the goal. }
The second part of this assignment that the student needs protected void wrapup()
to complete is the recovery of the path from start to goal { displayPath(extractPath());
that is found, with no side paths. We have the main }
search put every state that is checked onto the stack private Stack extractPath()
visitStack. The problem is then to write a helper { Stack path = new StackAL();
method extractPath, that extracts the path itself as a // code to extract path
// from visitStack here
stack, with goal at the bottom and start at the top. return path;
}
Here is the initial code for the DepthWalker class that
the student is given. It is a subclass of AutoWalker. private void displayPath(Stack path)
Recall that any such subclass needs to implement the { while(!path.isEmpty())
takeStep method and, optionally, the initialize and { WalkerState current =
(WalkerState)path.pop();
wrapup methods. We use an interface for Stack, with display().displayState(current);
implementing class StackAL, These are taken from }
materials developed for the College Board AP CS }
}
program, available at http://apcentral.collegeboard.com
pop to enqueue and dequeue. (We provide a Queue
8.2 Breadth-first search interface and implementation from the AP CS program.)
We can modify the depth-first search, once completed, to Note that the visitStack stack should not be changed.
become a breadth-first search simply by replacing the These two walkers demonstrate two standard search
searchStack with a queue, changing calls to push and strategies used for finding a goal and even for an optimal
solution to a problem, such as a shortest path.
214
8.3 Best-first search The advantages we see to using case studies include:
• Complexity in a controlled situation
A "best-first," "guided," or "heuristic" search is a search
• Introduction of objects early
based on a criterion for determining that some steps in the
search are more promising than others. In the case of the • Incremental introduction of topics
maze problem, we take the location with the shortest • Provide a familiar context for students throughout a
distance to the goal as the most likely to lead to the goal. course
In order to carry out a best-first search we replace the • Provide a realistic context for the application of
stack or queue used previously with a priority queue with concepts
the distance to the goal from a given state as the priority • Provide a context for introducing design patterns
For the priority queue we use the PriorityQueue
interface used for the AP CS program and provide a min- 10 References
heap implementation. This requires a class that contains Alphonce, Carl, and Phil Ventura, 2002. "Object-
an item (state) and its priority (distance to maze goal). Orientation in CS1-CS2 by Design," Proceedings of the
Otherwise we simply replace the searchStack with a 7thAnnual Conference on Innovation and Technology in
priority queue, using the methods add and removeMin in computer Science Education (ITiCSE 2002), 70-74.
place of push and pop.
Astrachan, Owen, Geoffrey Berry, Landon Cox, Garrett
This sequence of assignments gives examples of the use Mitchener, 1998. "Design Patterns: An Essential
of these three standard data structures within an Component of CS Curricula," ACM SIGCSE Bulletin v
interesting context. It also is the beginning of topics that 30 n 1, 153-160.
would be covered in a more advanced course on
Barnes, David, and Michael Kolling, 2003. Objects First
algorithms, such as finding the shortest path or
with Java, Prentice-Hall: New York.
developing a branch-and-bound algorithm.
Brady, Alyce, 2002. The Marine Biology Simulation Case
8.4 Classroom experience Study, The College Board: New York. Available from
http://apcentral.collegeboard.com. Accessed Nov., 2003.
One of the authors, Nevison, has used both the recursion
assignment and the depth-first, breadth-first, and best-first Bruce, Kim, Andrea Danyluk, Thomas Murtagh, 2001.
search assignments in a second computer science course, "A Library to Support a Graphics-Based Objects-First
with the focus on data structures. These assignments Approach to CS 1," ACM SIGCSE Bulletin v33 n1, 6-10.
worked quite well. The students liked working with a Christensen, Henrik, and Michael Caspersen, 2002.
problem with a visual component, and the visualization "Frameworks in CS1 - a Different Way of Introducing
provided feedback on the how their program was Event-driven Programming," Proceedings of the
working. For example, seeing a recursive or iterative 7thAnnual Conference on Innovation and Technology in
solution that continuously moves between two or a few computer Science Education (ITiCSE 2002), 75-79.
states demonstrates the problem of not keeping track of
where one has been previously to force progress toward Clancy, Michael, and Marcia Lin, 1992. "Case Studies in
the base case (the maze goal). the Classroom," ACM SIGCSE Bulletin v 24 n 1, 220-
224.
Another example of the effectiveness of visual feedback
is the assignment to implement the extractPath Gamma, Helm, Johnson, and Vlissides, 1994. Design
method for the depth-first and other iterative searches. Patterns, Addison-Wesley: Boston.
Students will often get a "solution" that compiles and Nevison, Christopher, and Barbara Wells, 2003.
runs, but when run marks a "path" from start to goal with "Teaching Objects Early and Design Patterns in Java
many side branches. This visual feedback shows that the Using Case Studies," Proceedings of the 8th Annual
program has problems and may provide clues as to what Conference on Innovation and Technology in computer
the problem is. Science Education (ITiCSE 2003).
Students find these assignments to be interesting and get Nygaard, Kristen, 2001. Invited Talk OOPSLA'01,
engaged with finding good solutions. Some students are Educators' Symposium
ready to take the problem a step further with an extra
credit shortest-path solution for the maze. Nygaard, Kristen, 2002. "COOL (Comprehensive Object-
Oriented Learning," (keynote address) Proceedings of the
9 Summary 7th Annual Conference on Innovation and Technology in
computer Science Education (ITiCSE 2002), 218.
We have presented an example demonstrating how one
can use case studies to teach introductory computer Proulx, Viera, 2000. "Programing Patterns and Design
science from the early in the first course through the Patterns in the Introductory Computer Science Course,"
material typically covered in the first year of Computer ACM SIGCSE Bulletin v 32 n 1, 80-84.
Science. We have had success with this approach in our Proulx, Viera, Jeff Raab, Richard Rasala, 2002. "Objects
own classes. from the Beginning," Proceedings of the 7th Annual
Conference on Innovation and Technology in computer
Science Education (ITiCSE 2002), 70-74.
215