University of Toronto
CSC148 --Introduction to Computer Science, Spring 1998


Assignment 4: Toy Train Set

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.


Introduction

In the working world, you will very rarely write a program from scratch. In general, you'll be working on an ongoing project that was started years ago, and your first job will be to understand how you fit in to it.gif This assignment is very realistic in that there is absolutely no way you're going to understand all of the code we give you in the time alloted; nor do you need to! Part of your work will be finding the bits that are relevant to your tasks.

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.


Part A -- Questions

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.

  1. Draw an inheritance diagram which includes all the classes defined in the program. If class B is derived from class A, then show an arrow pointing from B to A. If a class in the program explicitly inherits from a Java API class (e.g., Thread), then show this relationship as well in your diagram. To distinguish the Java API classes from the ones in our program, draw a rectangle around each Java API class name and an oval around each class name from our program.

    To simplify your diagram, omit all classes that extend Rail.

  2. How do Entitys know when to move?
  3. How does a Barn know what kind of Animal to create?
  4. Engines move() on their own, but other Cars only move when told to by an Engine. Why don't Cars move() on their own?
  5. Landscape is a two-dimensional grid of Plots. Entitys move around on the Landscape by hopping from Plot to Plot, and each Plot has a list of Entitys that are on it. For example, an Engine figures out what the next Plot is in the direction it's moving, tells its current Plot that it's leaving, and tells the new Plot that is has arrived. Where else are the Entitys stored, and why?
  6. How can Entitys figure out which Plot they are on?
  7. Explain what sequence of code is executed when someone clicks on the ``Accelerate'' button which causes the train(s) to speed up.

tex2html_wrap385 The answers to the questions, and an estimate of how long it took you to complete this part.


For Your Information

Here is some helpful information about the code:


Part B -- Improving Crashes

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

  1. The linked list is a doubly-linked list.
  2. When a Car crashes, it tells the Car in front of it that it needs to decouple, and the links are severed.

tex2html_wrap385 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.


Part C -- Fixing a Bug and Improving Animal Catchers

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.

tex2html_wrap385 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.


Part D -- Extending Animal Behaviour

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.gif Part of the marks will be for coming up with behaviour that is significantly different from the Animals that are already defined.

tex2html_wrap385 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.


Part E -- Big-oh

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:

  1. Assume that n Objects are to be inserted into a FlexList, using method insert1(). Use big-oh notation to express the number of times an array element is copied. (You may assume that n is a power of 2.) Show all the steps you took to arrive at your answer.
  2. With this technique, what is the maximum number of unused array locations at any one time? Give an exact answer (don't use big-oh) and express your answer in terms of the number of Objects the array held before the last insertion.
  3. Now assume that n Objects are to be inserted into a FlexList, using method insert2(). Use big-oh notation to express the number of times an array element is copied. (You may assume that n is a power of 2.) Show all the steps you took to arrive at your answer.
  4. With this technique, what is the maximum number of unused array locations at any one time? Give an exact answer (don't use big-oh) and express your answer in terms of the number of Objects the array held before the last insertion.

tex2html_wrap385 The answers to the questions, and an estimate of how long it took you to complete this part.

    figure287
Figure 1: Two ways of inserting into a ``flexible'' list.


Part F -- Fixing Those Other Array Problems

TrainSet and Plot maintain their lists of Entitys in arrays, so ArrayIndexOutOfBounds exceptions could occur. Fix this as follows:

  1. Modify FlexLists so that they store Entitys instead of Objects. This will save you some hassles in step 3.
  2. Complete the implementation of FlexList so that it includes all methods you'll need for step 3 (methods to remove Entitys, look them up, and so on). Include only one insert() method -- whichever you feel is most efficient, based on your analysis in Part E. Also, add a constructor that lets the client code choose an initial size for the array.
  3. Now change the starter code so that TrainSet and Plot use FlexLists instead of arrays. You will have to find every place in the code that uses those arrays and convert it. (There are not that many -- don't worry.)
Don't worry about using FlexLists to improve your solution to the array problem with Animal catchers from Part C.

tex2html_wrap385 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.


How to Hand in Your Assignment

You must clearly label each part of your work for this assignment, arrange them in alphabetical order (Parts A, B, C, D, E, and F) and put them all in an tex2html_wrap_inline409 by 11 inch envelope, As well, you must also hand in all the .java files that you have modified or created on a tex2html_wrap_inline413 inch floppy disk. You must include only those modified files, and there must be absolutely nothing else on the disk. The files must be in the top directory. Be sure that your name and student number is on that disk and put the disk in the envelope as well. Finally, don't forget to fill out a cover page and tape it to the front of the envelope.

Significant marks will be deducted if you do not follow these instructions.


Tentative Marking Scheme

  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


Footnotes
...it.
As an example, the first programming job the head TA ever had was working on a program that was made up of just over 500,000 lines of code in a team of five people. He would have had a terrible time if he hadn't had several professors who gave out huge programs during his undergraduate degree.
...coming.
One note: if an Entity is made to disappear, you'll have to be sure to remove it from both the TrainSet and its Plot. Also, if you remove an Entity that is another Entity's target, the latter Entity will generate an exception when it tries to get the removed Entity's location. We won't consider it a problem if this happens; we just want you to be aware it.
 


Diane Horton
Tue Mar 24 11:24:43 EST 1998