Due date: Saturday, November 15th at 8:00 A.M.

1 Purpose

In this project you will write a program which uses functions and makes use of arrays.

You will write another race track simulation, but this time there can be up to 20 cars on the track at the same time. Much of the behavior of the cars in this simulation will be similar to the car in the last project. BUT, when two cars collide, they crash and disappear from the track!

Since much of the description of this project is identical to the previous project, we will omit many details. You may need to refresh your memory by reading through the description of Project #4 before reading this project description.

2 Files Provided

Like the previous project, we will provide you with the following files:

multirace.x  (the executable)
primary_input
primary_output
animation_input

Please notice that for this project, the files primary_input and animation_input are VERY different. The primary_input file is the one we will use as our primary test case for grading your project. If your project is working correctly, it should also be able to handle more complicated inputs like the animation_input file, but we will use these harder test cases as secondary inputs when grading your project.

3 Project Desciption

3.1 Input Files

The input for this program will be slightly different from the previous project. Below is the animation_input file that we have given you:

12
40
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@      F      |      e       @@@@@@
@@@@@   F          | b          f  @@@@@
@@@        F  F    |    c            @@@
@@  F  *           | a    d       g   @@
@       F @@@@@@@@@@@@@@@@@@@@    F    @
@  F      @@@@@@@@@@@@@@@@@@@@         @
@@     F      *           F      F    @@
@@@       *            *      F      @@@
@@@@@  F     *     F            F   @@@@
@@@@@@          F     *  F   F     @@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
2
Y

As before, the first two numbers represent the number of rows and columns for the current track. (The maximum possible size is still 57 rows and 57 columns). After this you see the shape of the track. Notice that the data here is different this time. As before, the '@' symbols are walls, the '*' symbols are oil slicks, and the '|' symbols represent the finish line. Notice that there may be 'F' symbols (fuel supplements) displayed in the track diagram. For this project, all of the fuel supplements are worth 30 units of fuel, and their locations are determined by the positions of the 'F' symbols on the diagram of the track. As before, there could be anywhere between 0 and 40 fuel supplements on the track.

Any symbols other than '@', 'space', '|', 'F', or '*' are cars! In this example there are 7 cars, represented by the symbols 'a', 'b', 'c', 'd', 'e', 'f', and 'g'. There can be as many as 20 cars. As in the last project, all cars will start moving to the left.

After the diagram of the track, you will be given the number of laps for this race, and the same ``animation flag'' used in the previous project.

3.2 Fuel Supplements

All fuel supplements in this simulation are worth 30 units of fuel. This means that there is no longer a need to keep track of the amount of each supplement in an array.

3.3 Cars

In this project there could be as many as 20 different cars. All cars in this simulation will start off with 100 units of fuel. Each car starts off moving to the left. In this simulation, if a car runs out of fuel, the simulation does not end - instead, this car just stops moving. A car that has run out of fuel can still be involved in a crash if another car moves onto its location! Note that it is possible for all cars to run out of fuel before the end of the race, in which case the correct behavior for your program is an infinite loop where the cars just stay in one place and the race never ends.

Important: Your program will use parallel arrays to keep track of the cars. For example, in your prevoius project you probably had an integer variable to keep track of your car's fuel supply. In this project, you will need a whole array of integer values to keep track of the fuel supplies for all of the cars. You will probably have several arrays that will hold various pieces of information about the cars. When storing and retrieving the data from these arrays, it is very important that you index all of the cars in the correct order, based on their initial locations in the input file. (In other words, we have to all agree on which car will be car #0, which car will be car #1, etc.) As you are processing the input file, scan the rows from top to bottom, and within each row scan from left to right. The cars should be indexed as they appear when scanning in this way. If you take the animation_input file as an example, the indices of the cars are as follows:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@             |      0       @@@@@@
@@@@@              | 1          2  @@@@@
@@@                |    3            @@@
@@                 | 4    5       6   @@
@         @@@@@@@@@@@@@@@@@@@@         @
@         @@@@@@@@@@@@@@@@@@@@         @
@@                                    @@
@@@                                  @@@
@@@@@                               @@@@
@@@@@@                             @@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Note that once the cars are indexed intially, the indices will never change, even as the cars move around and possibly crash.

3.4 The Correct Algorithm

Most of the behavior for the cars is the same as before - they turn the same way just before hitting a wall; they behave the same way when they step on the finish line, or on an oil slick; they generate oil slicks the same way; laps are counted the same way; etc.

But having multiple cars makes the algorithm for the race a little more complicated. Below is psuedocode for the proper algorithm for implementing this simulation:

while no car has finished the race
{
  cycle through the cars that have not crashed and are not out of fuel
  {
    make the car turn if it is about to hit a wall
    move the car (leaving an oil slick behind if the car's fuel
        supply is divisible by 10).
  } 
  remove crashed cars from the race (if two or more cars are currently
    in the exact same location, then they have crashed)
  cycle through the cars that have not crashed and are not out of fuel
  {
    if the car is on the finish line, increase its lap counter
    if the car is on a fuel supplement, increase its fuel supply by
      30 units, and remove the fuel supplement from the track 
    if the car is on an oil slick, change it's direction, and remove
      the oil slick from the track
    decrease the fuel supply of the car by one unit
  }
  if you are in animation mode, or if the race is over
    draw the race
}

3.5 Crashes

Note that crashes only occur if two cars move onto the exact same location. Consider the following situation, involving cars 'X' and 'Y'. Imagine that car 'X' is moving to the right, and car 'Y' is moving to the left:
      X Y
On the next ``frame'', both of these cars will occupy the same position, generating a crash!


Now consider cars 'X' and 'Y' moving as before, but positioned like this:

      XY
After moving 'X' to the right, and moving 'Y' to the left, their positions now look like this:
      YX
Since the cars are never ``on the same spot'', they do not crash!

3.6 usleep

As in the previous project, you may want to use the usleep function to slow your simulation down. Be sure to remove all calls to usleep before submitting your project, or you will lose lots of points!

4 Required functions and implementation

This program must be implemented using many small functions.

For example, the following code counts as 6 lines:

/* I wonder what this will do... */

int x;
float y;

if (logical expression #1 &&         
    logical expression #2 &&
    logical expression #3)            /* line 1 */
{
   if (logical expression #4)         /* line 2 */
     x++;                             /* line 3 */
   y -= 4.0;                          /* line 4 */
}
else                                  /* line 5 */
   x = 7;                             /* line 6 */

Failure to comply with the above will result in a project grade of no more than 50 points out of 100.

Furthermore, you must provide a function prototype for every function in your project (other than ``main'').

Many of your functions may call other functions you have written. You should write and test each function separately, starting with the simpler ones, before implementing those which could depend upon them.

You may not use any global variables for this project! This means that you will declare your basic variables (including lots of arrays) in the function ``main'', and your functions will be passing lots of arguments to one another.

5 Checking Your Outputs

You should use the ``diff'' command to check your output for the primary case. For this project, you should use ``diff'' without specifying ``-bwi''.

6 Project requirements

All your C programs in this course should be written in ANSI C, which means they must compile and run correctly with cc -std1 -trapuv on the OIT UNIX Class Cluster. You will lose credit if your program generates any warning messages when it is compiled. Prototypes must appear for all functions used, and at most one return statement may be used in any function. Even if you already know what they are, you may not use any C language features other than those introduced in Chapters 1 through 9 of your textbook, plus those presented in lecture while these chapters were covered. In addition neither the goto nor the continue statement may be used, and the break statement may not be used to terminate a loop. Your program may not use the exit() library function at all. You must use character constants (i.e., 'A'), rather than numeric ASCII values anywhere character values are needed. Lastly, no global variables may be used. Using C features not in these chapters, or using global variables, the goto statement, the exit() library function, multiple returns, or break or continue in loops, will result in losing credit.

Your program must have a comment near the top which contains your name, login ID, student ID, your section number, your TA's name, and an original description of the action and operation of the program. In addition, you must have a short comment before each function explaining its action and operation. Your program should be written using good programming style and formatting, as discussed in class and throughout your textbook. For this project, style is considered to consist of:


7 Developing your program

You may want to skip this section at first, read the rest of the project, and come back to study it carefully when you are about to begin writing your program.

Because this project is larger than the previous projects, being able to determine what part of your code is causing an error is much more important. If you need to come to office hours, you will be expected to be able to tell us where the error is, or what you have done to try to locate it. This means having tested your functions, as explained below, so that you know which ones already work for sure. It also means it is absolutely necessary to develop your program in stages so that you are not trying to write and test all of the code at one time.

7.1 Program development strategy

As discussed in the earlier project assignments, it is very important to type in only a part of your program at a time and compile and test it, and verify that it is correct, before going on. For a program with functions, this means writing only one function at a time. It also means making sure that function is correct before calling it from your main function or another function. The way to determine if it is correct or not is to add test calls, or temporary statements just for the purpose of testing this function, to your program. You can add these calls at the beginning of your main function. The idea is that, having written a function, you know what it is supposed to do. Call it passing some sample values as arguments and print its return value if it has one, to make sure that it does its whatever it was supposed to do correctly. If it's supposed to change some values in an array, print the array after the test call to insure the function did what it should have. You should be able to figure out by hand what results the function was supposed to produce for the call you wrote. If it doesn't do what you think it ought, you need to find out why before going on!

It may be best for you to implement the shorter functions first. After you write and test these you will have more practice with functions, and can go on to write those which are a little more complex.

Due to the complexities of reading character input, and the possibility of error which may occur, it's extremely important to carefully print the input values which your program reads to insure it's reading its input data correctly! Often one of the first steps of writing a program can be to simply write the code which reads the input and test it by printing the input values as they are read, because if the input isn't read properly clearly no code after that will be able to work right, even if written correctly.

7.2 Finding compilation errors

Here are several common compilation errors having to do with functions produced by the cc compiler on our class machines and what they mean:


In this declaration, the type of ``X'' is not compatible with the type of a previous declaration of ``X''

(where X is the name of one of your functions, and this error occurs where the function is declared)

This means you called a function before it was defined, or before the compiler saw a prototype for it. The solution is to add a prototype for every function at the top of the program file as soon as it is written, which tells the compiler everything it needs to know about the function so it won't become confused in this way.

In this declaration, the number of parameters differs from an earlier declaration of this function

The function as written has a different number of parameters than the prototype which you wrote for it.

Non-void function ``X'' does not contain a return statement

You wrote a function which you specified should have a return value, but you didn't include a return statement anywhere inside it. If you want the function to return a value, you have to add a return statement. Or, if you don't need it to return anything after all, change its declaration to indicate that it doesn't return anything.

In the declaration of ``X'', the array bounds are incorrectly specified

(where X is the name of a two-dimensional array parameter in one of your function definitions)

You can omit the first subscript of a two-dimensional array parameter when defining a function, but not the second one. This error is usually caused by trying to write a two-dimensional array parameter with two empty sets of brackets, such as arr[][]. The number of columns must appear inside the second set of brackets.

In this statement, ``X'' does not point to an object type

(where X is the name of an array parameter in some function)

This is typically caused by the same problem as the previous error.

7.3 Program testing

Just because a function works correctly for one or two sets of inputs doesn't mean it always works right. You will need to think of a variety of different possibilities for the function's input values (arguments) and make sure it produces the right results in every case. A few minutes spent adding statements which test each function with varying values will be well worth it, if it saves you hours of trying to track down a bug later! Once you are convinced your function works correctly, just delete the test calls, and integrate the new function into the rest of your program by calling it where it is needed.

To illustrate the fact that correct results in one or two cases don't mean a function always works correctly, imagine that for some program you have to write a function which counts how many times a given number is located inside an array containing 10 integers, and returns the result. Its parameters are an array of integers and the value which should be searched for inside the array. Here is the function you wrote:


int count_quantity(int arr[], int num) {

  /* This function returns the count of how many occurrences of its
   * second parameter are found in its first array parameter.  The
   * array is assumed to have ten elements.
   */

  int count= 0, index= 1;

  while (index < 10) {

    if (arr[index - 1] == num)
      count++;

    index++;
  }

  return count;
}


To test this function you could write a small main function containing an array, call the function with that array and a value to search for inside it, and print the answer which was returned. You can tell what results it should produce from examining the array. For example:

int main() {
  int array[10] = {3, 1, 5, 1, 4, 7, 9, 4, 2, 1};

  printf("number %d was found %d times\n", 3, count_quantity(array, 3));
  printf("number %d was found %d times\n", 4, count_quantity(array, 4));

  printf("%d\n", count_quantity(array, 4));

  return 0;
}


You would see that the first test call returns and prints 1, and there is in fact only one 3 inside the array. The second one prints 2, and there are two 4s in the array. You might conclude that your function was correct, however, this is not the case! Altering the call to search for different values, or adding separate test calls, reveals that the call:


printf("number %d was found %d times\n", 1, count_quantity(array, 1));
          


would also print 2, however, there are three 1s in the array, therefore 3 should be the correct result printed! The problem is that the last array element is never examined, since the loop stops immediately when index reaches 10, and arr[8] was the last element tested. You could verify this by adding a debug printf statement in the loop printing each array element as it is examined. In this case, changing the loop condition to ``while (index < 11)'' would be one way of fixing the problem.

The crucial point is that testing the function by calling it in only a few cases is not sufficient to conclude that it is correct.

7.4 Program debugging

If random or unexpected values are printed some of the most common reasons are:


  1. One of your loops is examining elements which don't belong to the array (it has gone off either side of the array). Trace your code by hand with a diagram of the current values of the array, or add debug printf statements to see the values of the array subscripts which you are using, to see where the error might be happening.

  2. You have a function which returns values in some cases but not in others. This can be avoided by using only one return statement at the end of each function (as required above) to pass back a value which was computed or determined, rather than several return statements in different places in the same function.

  3. You may be printing or using values of variables which were not initialized. Initialize all variables, or print the value of each variable before using it, to see where you are using one that hasn't been initialized.

8 Academic integrity statement

Any evidence of unauthorized use of computer accounts or cooperation on projects will be submitted to the Student Honor Council, which could result in an XF for the course, suspension, or expulsion from the University. Projects are to be written INDIVIDUALLY. For academic honesty purposes, projects are to be considered comparable to a take-home exam. Any cooperation or exchange of ideas which would be prohibited on an exam is also prohibited on a project assignment, and WILL BE REPORTED to the Honor Council.


VIOLATIONS OF ACADEMIC HONESTY INCLUDE:


  1. failing to do all or any of the work on a project by yourself, other than assistance from the instructional staff.

  2. using any ideas or any part of another student's project, or copying any other individual's work in any way.

  3. giving any parts or ideas from your project, including test data, to another student.

  4. having programs on an open account or on a PC that other students can access.

  5. transferring any part of a project to or from another student or individual by any means, electronic or otherwise.


IT IS THE RESPONSIBILITY, UNDER THE UNIVERSITY HONOR POLICY, OF ANY STUDENT WHO LEARNS OF AN INCIDENT OF ACADEMIC DISHONESTY TO REPORT IT TO THEIR INSTRUCTOR.

9 Submitting your project

Be sure to remove all calls to the usleep function before submitting your project! Your project must be electronically submitted by the date above, to aviod losing credit as described on the syllabus. No projects more than two days late will be accepted for credit without prior permission or a valid medical excuse, as described on your syllabus. Only the project which you electronically submit, according to the procedures provided, can be graded; it is your responsibility to test your program and verify that it works properly before submitting. Lost passwords or other system problems do not constitute valid justifications for late projects, so do not put off working on your program or wait to submit it at the last minute!

Turn in your assignment using the ``submit'' program as before, except using ``5'' for the project number. You are to submit only the .c file containing your source code, not the executable version of your program! If your program is in a file named ``p5.c'', submit would be run as submit 5 p5.c.

About this document ...

This document was generated using the LaTeX2HTML translator Version 2K.1beta (1.61)

Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The command line arguments were:
latex2html -show_section_numbers -split 0 -no_navigation -no_footnode project5

The translation was initiated by Fawzi Emad on 2003-11-01


Fawzi Emad 2003-11-01

Web Accessibility