Project 2: Amazing Race
Due Dates
Design Document: Sunday, March 4, 2007, 11:59pm + 59 seconds
Final Project: Sunday, March 11, 2007, 11:59pm + 59 seconds
Contents
Objective
The objective of this project is to practice designing C++
classes following the principles of object-oriented programming.
^Return to top
Warning to Procrastinators
This is a thinking project. It will take more time to think about
the project than to code. This does not imply that coding will not
take a significant amount of time. Indeed, poorly-designed projects
will take much longer to code (and debug) than a well-designed
project. You will need the first week of this two week project
to come up with a good design!
^Return to top
Background
For this project you will be designing C++ classes to simulate
remote control cars operating in a race course. The race course is simply
a two-dimensional grid. The cars start out in the top row and attempt
to reach the bottom-left corner. This is not a straight shot because the
race course is littered with obstacles. The first car to reach the
bottom left corner of the grid wins.
The remote control cars being simulated have no sensors and
limited fuel capacity. You can only command the cars to move in one
of four directions (up, down, left and right). The car keeps moving
in that direction until it either 1) runs out of fuel, 2) reaches
the edge of the race course, and 3) crashes into an obstacle or
another car.
^Return to top
Assignment
Note: you must also complete and submit a design document 1 week prior
to the due date of the final project. See the Design
Document section.
In Project 1, the classes were designed for you. You implemented
some member functions and wrote the main program that used the
classes. In this project, the situation is somewhat reversed. The
main program is given to you and the design of the actual classes
is up to you. You do not have complete freedom, however, since your
classes must work with the given main program.
Your main assignment is to design and implement two C++ classes:
Car and RaceCourse. These are partially specified below.
Requirements for the Car class
The Car class must support the following methods:
// Move in this direction until you can't
void ZoomLeft() ;
void ZoomRight() ;
void ZoomUp() ;
void ZoomDown() ;
// Other Member Functions
Position GetPosition() const ;
unsigned int GetFuelLevel() const ;
These functions should do the obvious thing. The "zoom" functions
move the car in the specified direction until it runs in to something,
either a wall or a car. GetPosition() returns the current
position of the car. The type Position is defined in a
header file given to you: proj2.h
--- it is a simple data-only class (really a struct) that holds a
row and column number. Finally, GetFuelLevel(() should
return the current fuel level.
Note that when a car moves, its fuel level goes down by 1 unit for
each row or column traversed. If a car runs out of fuel, it is stuck
forever.
Requirements for the RaceCourse class
The RaceCourse class must support the following methods:
// Constructor with sizes, number of cars and positions
// of the obstacles.
RaceCourse(unsigned int rows, unsigned int cols,
unsigned int cars, const vector& obstacles) ;
// return pointer to Car number i.
Car * GetCar(unsigned int i) ;
// RaceCourse stats.
unsigned int GetNumOfCars() const ;
unsigned int GetNumOfRows() const ;
unsigned int GetNumOfCols() const ;
void StartRace() ;
RaceStatus GetRaceStatus() ; // const or non-const
unsigned int GetWinner() ; // const or non-const
// Use # for edges and obstacles, digits for car numbers,
// and . for a blank space. See sample output.
void PrettyPrintCourse() ; // const or non-const
Change: You can designate GetRaceStatus(), GetWinner()
and PrettyPrintCourse() as const or non-const as it fits your
design.
Initially, the cars are all positioned in the top row. Car # 1 should
in the leftmost column, followed by Car #2, Car #3, ... The number of cars
must not exceed the number of columns. Each car starts with the same amount
of fuel, specified in the constant InitialFuelLevel that is
defined in proj2.h.
The the status of the race course can be one of four values
- WAITING: the race course has been initialized
but has not yet started.
- STARTED: the race has begun and is ongoing.
- FINISHED: one car has reached the bottom left
corner.
- STALEMATE: the race has begun, but all cars
are out of fuel.
The status is represented as an enumeration type RaceStatus
defined in proj2.h. The status of the race
is reported by the GetStatus() method. If the race has finished,
then GetWinner() reports the winning car. The method
StartRace() must be invoked by main() before
it starts moving cars around. When StartRace() is called, the
status of the race course should change to STARTED. This is also
an opportunity for the RaceCourse object to do any "housekeeping"
before the race begins (if any such housekeeping is needed).
The RaceCourse object must maintain a certain level of internal
consistency. For example, two things (cars and obstacles) should not be
allowed to occupy the same position. Similarly, cars should not be allowed
to drive off the course (this will require some cooperation with the
Car class).
Many questions about the requirements for the Car and
RaceCourse objects can be answered by looking through the main
programs supplied. (See Testing section.) The
requirements define the interfaces between the main program and the
Car class and between the main program and the RaceCourse
class. The interface between the Car class and the
RaceCourse class has not been specified. This part is left
for you to design.
^Return to top
Grading
- A design document is due on Sunday, March 4, one week before
the final project. (See the Design Document
section.) The design document is 15% of the project grade.
-
Projects will be graded on five criteria: correctness, design, style,
documentation and efficiency. So, turning in a project that merely "works"
is not sufficient to receive full credit.
-
Part of your grade will also depend on having demonstrated that you have
diligently tested your own program, by creating and submitting your
own test main program. (See the Testing section.)
- The Academic Conduct Policy for
this course states that programming projects must completed by you own
individual effort.
-
Remember that the late policy is
a 25% penalty for submissions up to 24 hours late. Projects more than
1 day late will receive zero.
^Return to top
Implementation Notes
- You will certainly need to define other data members
and methods for the Car and RaceCourse classes. For example,
the constructors for the Car class are not specified. You
will need to figure out the function prototype of the constructor
that suits the needs of your design.
- We don't want to do dynamic memory allocation just yet,
So, proj2.h has some constants we need.
const unsigned int MaxCars=9 ;
const unsigned int MaxRows=50 ;
const unsigned int MaxCols=20 ;
- The pointers returned by GetCar() must be valid
for the lifetime of the race course. If you use a vector to hold
the Car, you must make sure that this vector does not
get resized. If the vector is resized, the Car objects
will be copied, which invalidates the pointers previously returned
by GetCar. The recommendation is that you use an
array of Car objects with MaxCars items.
- The main program will use the GetCar() function to
retrieve a pointer to a Car(). There is a reason for this
mechanism that will make more sense after we cover polymorphism.
The main program will then ask the car to move by invoking
a Car method, such as:
CarPtr1->ZoomDown() ;
This is equivalent to (*CarPtr1).ZoomDown() just
as in C for pointers to structs. In order for the Car to
ZoomDown, it will certainly need to consult the RaceCourse
it is in. How does the Car know which RaceCourse to use???
When a RaceCourse is constructed, it also initializes
the specified number of Cars. The RaceCourse must place
a pointer to itself in a Car data member. In C++ the keyword
this used in a member function means "pointer to the current
object". Thus, the RaceCourse constructor must store its own
this pointer in each Car object it initializes.
- Try not to use friends.
- If you find yourself writing methods for Car
that must access a lot of RaceCourse data members
or vice versa, then it is a sign that your objects are
poorly designed. Projects with poorly designed objects
will receive lower grades.
- If you use the vector container class, you need
to have the "using namespace std ;" directive.
- Beware of recursively including header files. The
Car class needs to know something about the RaceCourse class
and vice versa. Sometimes all you need is a forward class
declaration:
class RaceCourse ;
This just tells the compiler that RaceCourse is a class.
For example, this enough to declare pointers to RaceCourse.
- We will start counting the rows and columns with index 1.
This is so you can store "obstacles" around the perimeter of the
race course to form a wall. (Highly recommended.)
- Similarly, counting Car numbers from 1 is convenient,
since it lets us use 0 to represent an empty space in the race
course. Also, GetWinner() can return 0, when the race has not
yet finished.
- A car should not be allowed to move if 1) it is out of fuel,
2) the race has not yet started, 3) the race has finished.
- Whatever method you choose to represent the grid of
the race course, remember to initialize it properly.
^Return to top
Design Document
Thinking about object-oriented programming can be difficult and
takes practice. The primary objective of this project is to give
you practice thinking. The questions below are good starting points
for you to think about your design.
You must submit written responses to these questions by Sunday,
March 4, 11:59:59pm. Late submissions are not accepted for design
documents.
Answer the following questions using complete English sentences.
As usual, grammar and spelling counts. If you remember CUPS =
"Capitalization, Usage, Punctuation and Spelling" from elementary
school, they certainly apply here.
- In your design, how is the grid of the race course represented? What are
the advantages of this representation?
- In your design, where is the position of a car stored? in the
Car object? or in the RaceCourse object? or both?
- In your design, where is the fuel level of a car stored? How is it
updated after a car moves?
- Suppose the main program asks Car #1 to ZoomDown().
How does Car #1 know how far to move? Presumably a RaceCourse
method must be invoked. What is the syntax of such an invocation from
a Car member function?
- In your design, how is the STALEMATE race status determined?
What/how to submit for your design document:
- Download the plain text file: design.txt.
The file has the 5 questions listed above.
- Insert your answers in the plain text file using
a text editor.
- Submit the text file to the project 'proj2design' using the
Unix command:
submit cs202 proj2design design.txt
- You do not need submit any header files. Please do not
submit any MS Word files, PDF files, ... Just plain text, please.
^Return to top
Testing
You are provided with 3 main programs listed below. Your design and
implementation of the Car and RaceCourse classes must compile and run with
these 3 programs without any modification.
Warning: When your project is graded, it will also be tested
with additional main programs. So, having a project that works with
these programs is not a 100% guarantee. Your project must also
satisfy the requirements specified above.
You must also create and submit your own test program. Part of your
grade depends on this. You should show that you have fully exercised
your implementations of the Car and RaceCourse
classes. Note: It is acceptable to modify one the main programs
given below, but you must use a very different set of obstacles and
car movements.
Note: You will also need proj2.h (do not modify this
file).
^Return to top
Submitting in your program
Remember to submit the design document the first week!
Use the UNIX submit command to turn in your project. The
project name for Project 2 is 'proj2'. So, the Unix command will
look like:
submit cs202 proj2 ...
where ... is a list of files you wish to submit.
You should submit the following files:
- Car.h: Header file for the Car class.
- Car.cpp: Implementation file for the Car class.
- RaceCourse.h: Header file for the RaceCourse class.
- RaceCourse.cpp: Implementation file for the RaceCourse class.
- mymain.cpp: Your main program for testing.
- Any other files needed to compile and run your program.
Note: We will assume that your project will compile using:
g++ -Wall -ansi *.cpp
If this is not the case, submit a makefile.
^Return to top