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.
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.
- Each of the blocks will be exactly 1 cm square.
- The window enclosing the blocks must be a SimpleWindow object with size that is 12 cm wide and 7 cm high.
- Blocks cannot be started or moved to a location where any part of the block will extend beyond the boundary
of the window. For example, the closest a block can be to the top-left corner of the window is when its center
is at position (0.5, 0.5).
- Blocks can move one "step" in any direction of the compass (e.g. North, North-east, East, etc.).
Moving up or down means changing the X and/or Y location of the block by 1 cm. For example, to move North-east
would mean adding 1 to the block's current X position and subtracting 1 from the current Y position.
- Blocks are moved randomly, according to the following algorithm:
- Generate a random integer between 0 and 7.
- Use that integer to choose the direction to move according to the following diagram. For example, if you choose
the number 3, the block will be moved South-West from the current position (i.e. down and to the left). Important:
Use these values as specified: your grade depends on it!
- If the chosen move would take the block outside the window, the block must stay in the current position --
it does not move! Thus a block in a corner has a 5/8 = 62.5% chance of not being able to move. Of course the next
time around the loop, perhaps it will be luckier.
- The two blocks are considered to be touching if they overlap in any way, or if they touch along an edge or
even at a corner. For example, in the image above showing the end of the chase, the (X,Y) coordinates are (8.5,2.5)
and (7.5,3.5). This means the blocks touch at their corners, and the chase ended.
Advice: Draw a picture of touching blocks and their location values to help you determine the mathematical
rules for when two blocks touch. (Drawing pictures is always good, in our opinion.)
- To keep things simple, we will define the SimpleWindow that encloses the two blocks as a global variable. Thus
it is accessible to all functions in your file.
Important: There are places where you will need to know the width and height of this window. Use the member
functions of the SimpleWindow class to do this. Do not access global variables or constants that define these.
(Look through the EzWindows API Reference in Appendix E of the textbook for member functions that might help you
get this information about the SimpleWindow object.)
- The partially completed program that we supply you contains a function called pause() that is called after
we draw the blocks. This function's only purpose is to slow the program down so we can see the blocks clearly;
otherwise, the blocks move too fast. This function takes one int argument which controls how long the program pauses.
You may need to adjust the value depending on how fast your computer is. (This function is not very elegant!)
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:
- Print a suitable title or legend to cout when the program begins
- Prompts for the input values listed above. (Be sure to validate that the X and Y positions are legal starting
positions for blocks.)
- 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
- 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
- Print a title or legend about the program.
- 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.)
- Prompt for the second block's position, and read in its valid starting position. (Perform the same error checking
as in the previous step.)
- Prompt for the name of the log file. Read this value and define a file-stream object associated with this output
- 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.
- 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.
- Draw the two blocks in their initial position.
- Begin the loop: While there's more to do, do the following...
- Call the pause function to give us time to view the blocks in their new
- Calculate the new position for the first block using function NewPosition()
- If this position is within the window
- Call the LogMove() function to record
that move is being made
- Call the Erase() member function on
the block to erase it.
- Call the SetPosition() member function
on the block to change its
to the new position.
- Call the Draw() member function on
the block to display it in its new position.
- Else, if the new position is not valid
- Call the LogMove() function with arguments
that show the move was not allowed.
- Repeat steps 10-17 for the second block.
- Test if the two blocks are now touching
- If they're touching, or if we reached the maximum number of iterations,
the loop ends. Otherwise, continue the loop started at step 8.
- 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.
- Do not define any global variables of your own.
- All positions within the window for blocks should be of type double.
- You must provide both an electronic and a printed copy of your program. Submit an electronic copy using the
name chase.cpp. The electronic copy must be submitted prior to the beginning of your lab (the week of March
26). A submission under the wrong name will lose 10% of the grade. Attach a copy of the grading
criteria to your solution when you hand it in.
- The printed copy must be an exact duplicate of the electronic copy. It is to be submitted at the start of your
- The assignment is pledged. You may receive help only from the CS101 teaching assistants, the ITC consultants,
and the CS101 professors.
- Late homework assignments are not accepted.