CS101: Homework 6: Block Chase

Due at start of your Lab during the Week of March 26

Pledge: You may work on this pledged assignment work in groups of two or three. Your partners must be from your same lab section. If you violate the section rule, your grade on the assignment will be cut in half. Your group may discuss the content of this assignment and your approach with anyone, but your group must do all if its own work. The group must create the logic of the solution, type the code, and compile, execute, and debug its own program. Your group may not use any code developed by anyone else. Your group's source code submitted electronically must match exactly the code you deliver in your lab section. Only one member of the group should submit the program electronically and only one printed copy should be handed in.  The header comment section of your program should identify all members of the group. A person cannot be added to a group retroactively. So make sure your name is listed as part of your group's submission.

Block Chase

In this program you will use EZWindows to create a program in which two "blocks" wander around a window. One of our blocks is "chasing" the other, and if the two blocks ever touch the chase is over. Neither of our blocks is very clever -- they will both move randomly around the window. Your program will use a main loop in which each block moves one step away from its current location. Of course, because of the random motion they may never touch, so the user will specify a maximum number of times we move the blocks. You will also create a log-file that records information about each move both blocks make. You'll also need to get the inputs from the user that are needed to start the chase.

The first of the following images shows what the window might look like when the chase starts with the blue block at X,Y location (0.5, 0.5) and the red block at (7.5, 4.5). The second image shows how the chase ended after 8 iterations of the controlling loop. (These screen-captures are shown 50% smaller than actual size..)


We will give you a partially completed program that will show you how to create the blocks from the RectangleShape class, as well as how to draw and erase the blocks. (All this is done using the member functions of the EzWindows class RectangleShape and WindowObject, so it would be a good idea to look at the documentation for these in Appendix E. You'll use random number generation to determine which was to move each block, just like we used in hhe Ace High card game program earlier in the term.

Some Constraints

Your Problem

There are a number of subproblems you will need to solve, and you must write functions to handle them. For example, you must get a valid starting position for both blocks, you must calculate the location to move to next, you must determine if the possible new location is inside the boundaries of the window, and you must determine if the two blocks are touching.

The inputs to the program will be the starting location for the first block, the starting location for the second block, a file name for the log-file, the maximum number of iterations chase will run, and a seed value for the srand() function used in the program.

Your program will generate outputs as follows:

  1. Print a suitable title or legend to cout when the program begins
  2. Prompts for the input values listed above. (Be sure to validate that the X and Y positions are legal starting positions for blocks.)
  3. Information about each block's move (or attempted move). This will be printed both to cout and also to a file called the "log file". Important: We will supply a function LogMove() that you will use to do this, so you don't have to write code for this. Be sure to use our function because our grading method will rely on it.
  4. When the chase ends, print a message to cout indicating whether or not one block caught the other.

Of course the program will also move the blocks around, too.
Note: When you run your program, like all EzWindows programs you will see the control window open in addition to the SimpleWindow object you create yourself. The control window is where you type to extract info using cin and see output inserted to cout. When your program starts, if the windows overlap, use the mouse to move the control window so you can see both windows fully at the same time.

High-Level Solution Design

  1. Print a title or legend about the program.
  2. Prompt for the first block's position, and read in a valid starting position. (If the values entered are not a valid position, ask the user for another X/Y coordinate pair.)
  3. Prompt for the second block's position, and read in its valid starting position. (Perform the same error checking as in the previous step.)
  4. Prompt for the name of the log file. Read this value and define a file-stream object associated with this output file.
  5. Ask the user for the maximum number of loop iterations to run after the blocks are first drawn. The "chase" will end when the blocks have tried to move this number of times, or when the blocks touch each other.
  6. Ask the user for an int value to use as a seed value for the srand() function. If the user enters 0, use the system clock with srand() as we did in the "Ace High" program.
  7. Draw the two blocks in their initial position.
  8. Begin the loop: While there's more to do, do the following...
  9.       Call the pause function to give us time to view the blocks in their new location.
  10.       Calculate the new position for the first block using function NewPosition()
  11.       If this position is within the window
  12.             Call the LogMove() function to record that move is being made
  13.             Call the Erase() member function on the block to erase it.
  14.             Call the SetPosition() member function on the block to change its
                            location to the new position.
  15.             Call the Draw() member function on the block to display it in its new position.
  16.       Else, if the new position is not valid
  17.             Call the LogMove() function with arguments that show the move was not allowed.
  18.       Repeat steps 10-17 for the second block.
  19.       Test if the two blocks are now touching
  20.       If they're touching, or if we reached the maximum number of iterations, the loop ends. Otherwise, continue the loop started at step 8.
  21. After the loops ends, print a message indicating if the blocks caught each other or not.

Functions You Must Use

Here are the prototypes and documentation for the functions you must use. You should find one (or more?) other activities that are repeated in your code that could be turned into good functions, and you should create other functions as appropriate.

bool NewPosition(double OldX, double OldY, double &NewX, double &NewY,
			   string &Direction );
// You must write this function.  The first two parameters are the current
// position.  When the function returns, the 3rd and 4th parameters will
// contain the new position, chosen randomly as described above. When the 
// function returns, the last parameter will contain the "direction" of the
// move:  N or NE or E or SE etc. The function returns true if the new position
// is a legal position for a block inside the window.
void LogMove(ostream &fout, int ct, string who, bool MoveOK, string Direction);
// This function is supplied. Its first parameter is the file output-stream.
// The second is the iteration number of the main loop. The 3rd is a string that
// that names the block being moved (e.g. "Block 1" or "Block 2").  The 4th
// actual parameter should be set to true if the
// move is a legal one, false otherwise.  The last parameter is the "direction"
// string passed back by NewPosition() that indicates which way we're trying to move.
bool IsTouching(double x1, double y1, double x2, double y2);
// You must write this function!
// This function returns true or false to indicate if the block centered
// at (x1,y1) is touching the block centered at (x2,y2).
bool ValidPosition(double x, double y);
// You must write this function!
// This function returns true or false to indicate if a 1 cm square block
// centered at (x,y) is contained inside the SimpleWindow W.  (W is a
// global variable.)

void pause(int count);
// This function pauses the program by repeating useless math
// calculations.  The argument controls how long it pauses.
// This function is given to you.

Other Requirements