Due: Wednesday 8 April, 6 p.m.
This assignment is worth 10 marks towards your grade in this course.
For this assignment, you will work with a Java program which simulates
an electric train set. You will find the source code for this program
on the course web page. The assignment consists of several parts.
Each involves writing only a small amount of code, usually
no more than 30 lines.
You will probably spend most of your time understanding the program.
Begin the assignment by running the program (the main class is called A4Main) and experiment with the various features of the program. You will be prompted for a file name -- navigate to the directory where you saved the assignment files, and you'll find Track.in. Select that. When the program starts (you may have to wait several seconds), you'll see a simple picture of a train set, and some little rectangular barns. Buttons along the right hand side allow you to start the train set running, change the speed of the train, and so on. Once the train set is running, you'll see a train moving on the track, and people and cows coming out of the barns and wandering around. Notice that some of the rails on the track are ``SwitchRails''. You can click on a SwitchRail while the program is running to change the direction a train will take when in moves through that rail.
If you let the program run for a while, you'll probably get some ArrayIndexOutOfBoundsExceptions. Don't worry -- you'll fix those as part of your assignment.
Note that there is currently only one train. To test the code you are going to write, you'll need at least one more. Trains are formed in A4Main; one is commented out, so to get it back you can uncomment it. And you can mimic this code to add more trains if you need them. As you can see from the code, each train that you add needs a speed, a direction, and a location. Note that there must be a Rail on that location, oriented properly, in order for the train to work.
Next, read this handout. (All of it!) Don't worry about understanding all of it right away; this first read-through is intended to give you an idea of the sort of things you'll be doing.
Now it's time to start really looking at the code. Focus first on the relationships among the classes, then on the interfaces to the classes, and then finally (and only when you need to) look at the implementation details within the classes.
Think critically when you read our code. It's far from perfect, and we suspect that you'll see lots of things that you don't like, ranging from the design to the style to the comments. This program has evolved over two years, and that's one of the reasons why it may not be consistent.
Answer the following questions, which are designed to help you work your way through the code. Questions 2-7, together, should take no more than a page to answer -- probably quite a bit less.
To simplify your diagram, omit all classes that extend Rail.
The answers to the questions, and an estimate of how long it took you
to complete this part.
To get an integer ranging between all
possible int values (positive and negative), use
TrainSet.numberGenerator.nextInt(). If you want a random number
in a specific range,
between 0 and 7, for example, you can use
Math.abs(TrainSet.numberGenerator.nextInt()) % 8.
Component is an abstract class in package java.awt. Component is the base class for all user interface objects, such as buttons, scroll bars, and text areas. A Container is an abstract subclass of Component that can contain other Components.
Frame is a subclass of Window, which is itself a subclass of Container. The TrainSet is a subclass of Frame, and is the window that contains the whole visual part of the program.
Panel is a subclass of Container. The TrainSet has two Panels: one to contain the buttons (Run, Accelerate, etc.), and one (called Landscape) to contain the train track and the various Entitys.
Canvas is a subclass of Component, and can be drawn upon. The class Plot in this assignment is a subclass of Canvas, and thus can be used to draw graphics. Each Plot is a little piece of the picture of a train set.
All Threads have start(), stop(), suspend(), resume(), and sleep() methods. The first four should be fairly self-explanatory. Thread.sleep() causes the Thread to pause for a specified amount of time and then automatically start up again. Take a look at the last method in Entity.java to see how this is used.
Trains are currently a singly-linked list of Cars. All trains have an Engine at the front, and it pulls the rest of the Cars. When the Engine moves, it tells the following Car to move, then that Car tells its following Car to move, and so on.
Currently, when trains collide the Car that was hit stops moving, and everything in front of the crashed car decouples from it and continues merrily on its way. This is great, but the link to the crashed car remains, which is silly since the crashed car and those behind it aren't part of the train anymore. Your job is to modify the Car class so that
A printout of any classes you modified to fix
this as well as a copy of the .java files on disk (see section on
``How to hand in your assignment''). On your printouts, you must
clearly identify each place where you have made modifications
using a pen or a highlighter. Also hand in an estimate of
how long it took you to complete this part.
Engines pick up Animals. As a bit of history, trains used to be derailed when they hit cows and other obstructions, so the cow catcher was invented. It's an iron frame that forms a ``V'' in the front of the engine, and brushes obstructions out of the way.
We decided that cow catchers weren't quite fun enough, so we decided to implement Animal catchers, which scoop up Animals rather than move them aside. Those Animals are suspend()ed, so they stop trying to move. (If the Engine ever crashes, they are resume()d.)
Fortunately, we didn't quite get it right. (Really! We had a bug.) So if too many Animals are picked up we get an ArrayIndexOutOfBounds exception. Your job on this part of the assignment is to find out where this bug happens and fix it. Do this in the simplest way possible -- if there isn't room, just don't pick up the Animal.
Next, add a bit of code that will slow down an Engine whenever it picks up an Animal. We leave it up to you how to do this, and how much to slow it down.
A printout of any classes you modified to fix
this as well as a copy of the .java files on disk (see section on
``How to hand in your assignment''). On your printouts, you must
clearly identify each place where you have made modifications
using a pen or a highlighter. Also hand in an estimate of
how long it took you to complete this part.
Cows move in a random direction -- they inherit this behaviour from Animal. Although class Person extends Animal, it overrides this random behaviour; Persons have a target (an EntityGenerator) that they move toward. This target is obtained using the TrainSet.getEntityGenerator() method. (TrainSet also has a getEntity() method which returns an arbitrary Entity.)
Your job here is to add another subclass of Animal: Dog. Dogs are less discriminating than Persons, and will happily move toward any Entity, not just EntityGenerators. (Make sure that they don't choose themselves as a target!)
You'll find that when you start to write the Dog.takeTurn() method, you'll be duplicating a lot of code that already exists in Person.takeTurn(). This, as you know, is a bad thing.
To avoid writing repetitive code, modify Animal so that it has an instance variable target, and new behaviour as follows: if an Animal's target is null, then it moves randomly. If its target is non-null, it moves toward that target. Note that Person will need to be changed to take advantage of this. Also, with this change in Animal, Dog becomes really easy to write!
Now add one more subclass of Animal (or a subclass of Cow,
Person, or Dog) with significantly different behaviour from
other types of Animals. You can go to town here; feel free to
be creative. Possibilities include making Animals that avoid
other creatures, Animals that affect other nearby Animals in
some way, and Animals that don't step on Rails
if a train is coming.
Part of the marks will be for coming up with behaviour that
is significantly different from the Animals that are already
defined.
Printouts of all the classes that you have
modified for the new feature as well as a copy of each of the
.java files on disk (see section on ``How to hand in your
assignment''). On your printouts, you must clearly identify each
place where you have made modifications using a pen or
a highlighter. Also hand in an estimate of how long it took you to
complete this part.
As you saw, using arrays can lead to bugs because arrays have fixed size. In Part C, you eliminated one such bug in a simplistic way. In this section, you will compare two better ways of dealing with this limitation without using a linked data structure such as a linked list.
A FlexList maintains a list of Objects in an array. Initially that array can only hold 1 Object. Only insertions are allowed; there is no way to remove an Object from a FlexList. There are two ways to add new Objects: FlexList.insert1() and FlexList.insert2(). Both create a new, larger array when more room is needed, and copy the contents of the old array into the new one. But insert1() creates a new array with just one more location than the old one, while insert2() creates an array twice the size of the old one. The code for FlexList is given in figure 1.
Answer the following questions about the relative efficiency of these two methods:
The answers to the questions, and an estimate of how long it took you
to complete this part.
Figure 1: Two ways of inserting into a ``flexible'' list.
TrainSet and Plot maintain their lists of Entitys in arrays, so ArrayIndexOutOfBounds exceptions could occur. Fix this as follows:
Printouts of all the classes that you have modified for the new
feature as well as a copy of each of the .java files on disk
(see section on ``How to hand in your assignment''). On your
printouts, you must clearly identify each place where you have made
modifications using a pen or a highlighter. Also hand in an estimate
of how long it took you to complete this part.
Significant marks will be deducted if you do not follow these instructions.
5 - Part A (Questions) 10 - Part B (Improving crashes) 10 - Part C (Fixing a Bug and Improving Animal catchers) 20 - Part D (Extending Animal behaviour) 15 - Part E (Big-oh) 20 - Part F (Fixing Those Other Array Problems) 5 - Comments 10 - Programming style overall 5 - Professional presentation (quality of writing, organization, etc.) ---- 100 - total