be prepared ap - com sci gate · 2010. 7. 18. · cs-2 chapter 6. case study 6.1. introduction the...

30
B B e e P P r r e e p p a a r r e e d d for the A A P P * * AP and Advanced Placement are registered trademarks of the College Entrance Examination Board, which does not endorse this book. C C o o m m p p u u t t e e r r S S c c i i e e n n c c e e E E x x a a m m Maria Litvin Phillips Academy, Andover, Massachusetts Practice exam contributors: H. Donald Allen and Craig Morgan Steele Troy High School, Fullerton, California Sally Bellacqua and Mary Dring Johnson Thomas Jefferson High School for Science and Technology, Alexandria, Virginia Skylight Publishing Andover, Massachusetts

Upload: others

Post on 09-Sep-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

BBee PPrreeppaarreeddfor the

AAPP** AP and AdvancedPlacement are registeredtrademarks of the CollegeEntrance ExaminationBoard, which does notendorse this book.

CCoommppuutteerrSScciieenncceeEExxaammMMaarriiaa LLiittvviinnPhillips Academy, Andover, Massachusetts

Practice exam contributors:

H. Donald Allen and Craig Morgan SteeleTroy High School, Fullerton, California

Sally Bellacqua and Mary Dring JohnsonThomas Jefferson High School for Science and Technology, Alexandria, Virginia

Skylight PublishingAndover, Massachusetts

Page 2: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

Copyright © 2000 byMaria Litvin and Skylight Publishing

This material and the source files are provided to you as a supplement tothe Be Prepared for the Computer Science Exam book. You are notauthorized to publish or distribute them in any form without ourpermission. However, you may print out one copy of this chapter andfiles for personal use and for face-to-face teaching for each copy of theBe Prepared book that you own or receive from your school.

Library of Congress Catalog Card Number: 99-095124

ISBN 0-9654853-6-6

Skylight Publishing9 Bartlet Street, Suite 70Andover, MA 01810

web: http://www.skylit.come-mail: [email protected]

[email protected]

2 3 4 5 6 7 8 9 10 ML 03 02 01 00 99

Printed in the United States of America

Page 3: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

CS-1

Chapter 6.Chapter 6. Case StudyCase Study

6.1. Introduction................................................................................................................... 26.2. The RandGen Class .................................................................................................... 36.3. Part 1: One Fish in One Dimension .............................................................................. 66.4. Part 2: Many “Fishes” in Two Dimensions ................................................................ 10

6.4.1. utils............................................................................................................... 116.4.2. Position ....................................................................................................... 136.4.3. Neighborhood.............................................................................................. 146.4.4. Fish and Environment ............................................................................... 156.4.5. Simulation and Display .......................................................................... 216.4.6. main ................................................................................................................. 22

6.5. Appendix: Doing It From Scratch? ............................................................................. 23

Page 4: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

CS-2 Chapter 6. Case Study

6.1. Introduction

The Case Study is a component of AP CS exams that is based on a complete smallsoftware project. You have to get familiar with the case study’s features and code and beready to answer multiple-choice and free-response questions based on these features andtheir implementation. The case study includes several C++ classes and small clientprograms that use these classes. The Exam Development Committee provides adescription of the case study, its complete code, and some sample questions and exerciseslong before the exam. The same case study is used for several years. You will receive acopy of the case study code at the exam, but there is not enough time to read it on the spot— students are expected to know it quite well beforehand, and it is provided at the examonly for reference.

The case study for May 2001 will be Marine Biology by Mike Clancy, Owen Astrachan,and Cary Matsuoka. Its full description in PDF format and complete code are available atThe College Board's AP* CS web site:

http://apcentral.collegeboard.com

This case study involves simulating the random movement of particles (“fish” in a “tank”),but the emphasis is more on software development methodology rather than on a realisticmarine biology application. As the authors point out a couple of times, tongue in cheek,“we will verify this later with the biologists.” The case study stays within the C++ subsetas defined in the AP CS program. In order to understand the code, you must be familiarwith C++ classes, constructors with initializer lists, and overloaded operators. At thesame time, the case study hints at object-oriented programming (OOP), modularity,reusability of code — topics that you have perhaps avoided so far. At the practical level,you have to know how to handle projects with multiple header files and source modules.Chapter 14 in C++ for You++, Modularity, offers an introduction to that:

http://www.skylit.com/faqs/ch14.html

Elsewhere on our website you can find instructions on how to set up projects with differentcompilers:

http://www.skylit.com/faqs/compiler.html

The Marine Biology case study consists of two parts. Part 1 is a warm-up mini-projectthat introduces the RandGen class and uses it to simulate random movement of a singleparticle (“fish”) in one dimension. The case study doesn’t go into the implementation ofthe RandGen class, but just describes and uses its public functions. The code then defines

* AP and Advanced Placement are registered trademarks of the College Entrance Examination Boardwhich does not endorse this book.

Page 5: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

Chapter 6. Case Study CS-3

one class, AquaFish, which represents one fish in a “narrow” (one-dimensional)aquarium tank.

Part 2 extends the application into a rectangular area in two dimensions and handlesmultiple “fishes.” This part gets quite complex, with six interacting classes and anadditional utils.cpp module. After looking at the case study code one may wonder whyso much code is necessary to accomplish a fairly straightforward simulation. This is agood question and we briefly address it in an Appendix (Section 6.5). In any case, the casestudy is probably not too far from how things are sometimes done in the real world. One ofthe goals of Part 2 is to introduce students to the realistic task of reading, understanding,and modifying someone else’s rather convoluted code. (According to the case studynarrative, the code presumably had been written several years earlier by biology researchstudents.) The authors were also constrained by the C++ subset, which excludes such C++features as friends and inheritance. The latter allows a programmer to define hierarchiesof related objects, which is the defining feature of OOP.

6.2. The RandGen Class

The RandGen class provides functions that return random numbers. More precisely, thesenumbers are called pseudorandom because they are generated according to somealgorithm, as opposed to falling randomly from heaven. But they are distributed fairlyuniformly and meet some other statistical criteria for “randomness.” If you peek insiderandgen.cpp (which you are neither required nor supposed to do), you will see that ituses the srand function to “seed” the random number generator and the rand function togenerate random integers. These functions from the standard C/C++ library have beenfamiliar to programmers for many years and are standard in ANSI C, Windows, and Unix.A seed is used to initialize a sequence of random numbers; different seeds result indifferent sequences.

The RandGen class provides an interface with two constructors and two (overloaded)RandInt member functions:

RandGen randomVals; // Creates a random number generator // (or, as we say in OOP, // "random number generator object") // with un unpredictable seedRandGen randomVals(int s); // Creates a random number generator with // the given seed sint randomVals.RandInt(int n); // Returns a random integer x: 0 <= x <= n-1int randomVals.RandInt(int m, int n); // Returns a random integer x: m <= x <= n

It also has two RandReal member functions, which are not used in the case study code butcan potentially come up in questions.

Note the following properties of RandGen:

Page 6: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

CS-4 Chapter 6. Case Study

1. The default constructor (i. e., the constructor with no arguments) seeds the randomnumber generator with a different seed each time the program is executed. Thisresults in a different sequence of random numbers each time you run your program.

2. Another constructor, with one argument, allows you to seed the random number

generator with a specified seed. If you use the same seed each time you run yourprogram, then it generates the same sequence of random numbers on each run — afeature useful for debugging.

(This is sort of the opposite of what you might be used to with the rand function.In order to generate different sequences of random numbers with rand you have toseed the random number generator with some “random” seed yourself, using thesrand function. The computer’s system time is customarily used for that purpose.For example:

srand(unsigned(time(0))); // Seed the random number generator // based on the current system time In fact, that’s exactly what RandGen’s default constructor does.)

3. Once you have initialized the first RandGen object (i.e., the first instance of the

RandGen class) anywhere in your program, either with the default constructor orwith a specified seed, all other instances of RandGen will skip initialization anddraw random numbers from the same sequence. This means you cannot obtain twodifferent sequences generated with different seeds inside the same run of theprogram. For example:

RandGen r1(2001); // Defines the first RandGen object // seeded with 2001 RandGen r2(2002); // Defines a second RandGen object, but the // seed parameter, 2002, is ignored -- it will // draw random numbers from the same sequence // as r1

(This is understandable since RandGen is based on srand and rand, and thesefunctions support only one seeded sequence of random numbers at a time. You maywonder how r2 knows that r1 exists. It turns out that the RandGen class has astatic data member, ourInitialized, which is shared by all instances of theclass. ourInitialized is initially set to 0; once the first instance of the class isinitialized, ourInitialized is set to 1 and all other instances skip the call tosrand. Static class members are not in the AP subset.)

4. RandInt is similar to the random(n) function defined in Borland compilers: it

returns a random integer from 0 to n-1 (n is not included). For example,randomVals.RandInt(2) returns 0 or 1 with equal probabilities.RandInt(k,n) on the other hand, returns random numbers from k to n includingboth ends, k and n.

Page 7: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

Chapter 6. Case Study CS-5

5. randVals.RandReal() returns a random real (double) number 0 ≤ x < 1.Actually, the smallest possible distance between these random “reals” is1/RAND_MAX. randVals.RandReal(a,b) returns a random real numbera ≤ x < b. The RandReal functions are not really used in the case study code,except inside the RandGen class itself.

53

Consider the following program:

int main(){ RandGen r1(0); RandGen r2(0); int i, sum = 0;

for (i = 0; i < 100; i++) { sum += r1.RandInt(1, 3) - r2.RandInt(1, 3); } cout << sum/100. << endl;

return 0;}

Which of the following best describes the outputs when this program is executed a fewtimes?

(A) The output is always 0.(B) The output is always 1.(C) The output is always 2.(D) The output is always the same number in the range from -0.3 and 0.3 (but not

necessarily 0).(E) The output each time is a different number in the range from -0.3 to 0.3.

Page 8: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

CS-6 Chapter 6. Case Study

Æ Even though r1 and r2 are both seeded with 0, only the first initialization actuallytakes place (as explained above). The statement

sum += r1.RandInt(1, 3) - r2.RandInt(1, 3);

draws two consecutive random numbers from the same sequence. This sequence is thesame for all runs of the program because the random number generator is seeded with 0when r1 is defined. This eliminates E. The numbers returned by RandInt(1,3) rangefrom 1 to 3, inclusive. Therefore, sum may be incremented by as much as 2 ordecremented by as much as 2 on each iteration, whatever the difference might be; sum mayalso remain the same if that difference is 0. We cannot be sure that the program alwaysprints 0, but, if our random number generator is any good, we cannot accumulate a verylarge sum. (According to rules of statistics, it is rather unlikely that sum will go beyondtwo times the standard deviation, which is here approximately equal to 11.5. So theoutput will be somewhere between -0.3 and 0.3). The answer is D. Ã

6.3. Part 1: One Fish in One Dimension

Part 1 of the case study is a warm-up exercise on how to use the RandGen class in arandom walk simulation. Random walk refers to a simulation where a particle jumpsrepeatedly from its current position to one of the neighboring positions, chosen randomlyamong all its neighbors. You can ask a number of questions about random walk, such as:How far from the origin, on average, will the particle end up after n steps? How manytimes will the particle hit the origin in n steps? What is the probability that the particlewill ever reach a certain point within n steps? and so on.

In Part 1 of the case study, a particle (a “fish”) moves between discrete points in onedimension. There are two directions, “left” and “right,” and they are chosen with equalprobabilities. The fish moves on a segment of a certain length (a “tank”) and we count thenumber of times the fish bumps into the left and right walls of the tank.

The case study uses the AquaFish class to represent one fish in a tank, to simulate itsrandom-walk movement, and to count the number of bumps. In the chosen implementation,a “fish” (i.e., an AquaFish object) is pretty smart: not only does it store information aboutthe tank’s size, it also remembers its own position and the current count of bumps and evenknows whether to generate a debugging printout:

Page 9: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

Chapter 6. Case Study CS-7

class AquaFish{ public: AquaFish(int tankSize); void Swim(); // Swim one foot. int BumpCount() const; // Return the bump count.

private: int myPosition; int myBumpCount; int myTankSize; bool myDebugging;};

The tank size is passed to the AquaFish constructor and the bump count is returned by theaccessor member function BumpCount. The Swim member function implements one stepin a random walk.

The constructor uses an initializer list to set the tank size and the initial position in themiddle of the tank. It also zeroes out the bump count and enables debugging printouts:

AquaFish::AquaFish(int tankSize) : myPosition(tankSize/2), myTankSize(tankSize), myBumpCount(0), myDebugging(true){}

Page 10: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

CS-8 Chapter 6. Case Study

The core of the simulation is implemented in the Swim function:

void AquaFish::Swim(){ RandGen randomVals; int flip;

if (myPosition == myTankSize - 1) { myPosition--; } else if (myPosition == 0) { myPosition++; } else { flip = randomVals.RandInt(2);

if (flip == 0) { myPosition++; } else { myPosition--; } }

if (myDebugging) { cout << "*** Position = " << myPosition << endl; }

if (myPosition == 0 || myPosition == myTankSize - 1) { myBumpCount++; }}

Or, in a slightly shorter version (without the redundant braces and the debugging printout):

void AquaFish::Swim(){ RandGen randomVals;

if (myPosition == 0) myPosition++; else if (myPosition == myTankSize - 1) myPosition--; else { if (randomVals.RandInt(2) == 0) myPosition++; else myPosition--; }

if (myPosition == 0 || myPosition == myTankSize - 1) myBumpCount++;}

Page 11: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

Chapter 6. Case Study CS-9

The Swim function keeps the fish within the tank. The case study briefly discusses themerits of placing myDebugging inside the AquaFish class. (It would be better as astatic member, but this is not in the subset. Otherwise, it just could be a global constant.)

Note one peculiarity of AquaFish’s implementation: randomVals is constructed locallyinside Swim, presumably each time it is called. This is misleading. Actually, the randomnumber generator will be initialized only once: when randomVals is constructed for thefirst time in the first call to Swim. So the AquaFish class is dependent on this ratherunusual property of the RandGen class. A different design would have randomValsconstructed outside Swim: it could be a static member of AquaFish or, perhaps,AquaFish could be derived (inherited) from RandGen (but neither option is in the APsubset).

Part 1 also provides a test program aquamain.cpp that runs simulations.

54

Suppose we enter 5 for the tank size and 36 for the number of steps in an aquamain run.What will be the expected average bump count after several such runs?

(A) 6(B) 9(C) 12(D) 18(E) 144

Æ Strictly speaking, this is math. But it isn’t very deep, and it helps to have some ideawhat to expect in a given simulation when we test our program.

The fish starts out in position 2. After one step it goes to either 1 or 3. After another stepit can either reach 0 or 4 (with a bump) or return to 2 with no bump. Of all four possibletwo-step sequences (right-right, left-left, left-right and right-left), two result in a bump. Ifthe fish is in position 0, then after one step it goes to 1 and after another step it either goesback to 0 (with a bump) or goes to 2. A similar path applies to position 4. As we can see,it makes sense to follow fish movements in pairs of steps. You can sketch a diagram of allpossible pairs of steps from all even positions. No matter whether the current position ofthe fish is 2, 0, or 4, after a pair of steps it has a 50 percent chance of gaining one bump. In36 steps there are 18 pairs and, on average, half of them will result in bumps. The answeris B. Ã

Page 12: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

CS-10 Chapter 6. Case Study

6.4. Part 2: Many “Fishes” in Two Dimensions

Part 2 of the case study simulates the movements of several “fishes” in a rectangular area,represented by a two-dimensional array. The fishes cannot collide, that is each element ofthe array may hold at most one fish. The movements of the fishes are synchronized so thatin each step of the simulation each fish moves into one of the vacant neighboring cells (ifany). If all neighboring cells are occupied, the fish stays in its current position. Becausethey cannot collide, the order in which the fishes are processed is important. In thissimulation the fishes are processed left to right along each row starting from the top rowand going down:

for (r = 0; r < NumRows(); r++) for (c = 0; c < NumCols(); c++) ...

This simple model is represented in a rather elaborate set of classes. Each class ispackaged in its own pair of .h and .cpp files. (This is not a C++ requirement, but it is acommon practice.) The classes are said to represent objects: an “environment” object, a“display” object, a “fish” object. As the case study booklet explains, “all the class namesare nouns; the naming reflects their roles as types of objects.”

This is a step toward OOP, but only the first step. A true OOP application usuallyimplements a hierarchy of objects, using inheritance (not in the AP subset). The designdecisions in OOP allow a lot of freedom in defining objects, their relations, and functions.The central concept is that each object sort of “knows” how to handle itself. In the casestudy, for example, the Move function is placed within the Fish class, so a fish knows howto “swim.”

The code for Part 2 comprises nine modules (Table 1). The authors offer a “top-down”approach to analyzing the fishsim application: first look at the main program; then takethe executable program and experiment with it by running it with different data; thenexamine the higher-level classes, Environment, Fish, Simulation, then proceed to thelower level classes, Display, Neighborhood, Position. The experimentation partmay be fun, but it is also time-consuming. We can save a lot of time by going to the sourcecode first. Our approach here complements the case study booklet: it is a “bottom-up”approach: first we want to look at the lowest-level functions and classes, starting withutils.h and utils.cpp, then proceed to position.h and position.cpp, and so on.

Page 13: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

Chapter 6. Case Study CS-11

Files Class Functionality

fishsim.cpp Main program

environ.henviron.cpp

Environment Represents a 2-D grid

fish.hfish.cpp

Fish Represents one fish in the environment

simulate.hsimulate.cpp

Simulation Runs one or several stepsin the simulation

display.hdisplay.cpp

Display Displays the environment

nbrhood.hnbrhood.cpp

Neighborhood Represents a list of positions

position.hposition.cpp

Position Represents a position on a 2-D grid

utils.hutils.cpp

Contains IntToString, Sort, andDebugPrint functions

randgen.hrandgen.cpp

RandGen Implements pseudorandom numbers

Table 1. The case study files

6.4.1. utils

utils.cpp contains three free-standing functions (i.e., functions that are not members ofany class) that didn’t quite fit anywhere else. utils.h contains their prototypes.

The first function,

apstring IntToString(int n);

converts an integer into an apstring. It first builds a string in reverse order: starts at therightmost digit and proceeds to the left. The characters are appended to the string one byone, which may be quite inefficient: the string has to be expanded, reallocated, and copiedseveral times. The code then “unreverses” the string, by appending characters one by oneto the final result.

Normally such a function wouldn’t be written from scratch: some library functions orclasses would be used. A shorter solution, for example, may rely on the ostrstringclass:

...

Page 14: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

CS-12 Chapter 6. Case Study

#include <strstream.h>

apstring IntToString(int n){ char ascii[100]; // The output goes into this array ostrstream os(ascii, 100); os << n << ends; // Ends appends the terminating // null character return apstring(ascii);}

But standard arrays and ostrstring are not in the AP subset.

The second function, Sort, implements Selection Sort (see Be Prepared, p. 76) on anarray of Fish, according to their positions. It turns out that this function is never called —perhaps it is reserved for future exam questions!

The third function, DebugPrint, generates debugging outputs with different indentationand different levels of detail depending on the value of the global variable

int LEVEL_OF_DEBUG_DETAIL = 0;

defined in the same file. The case study advocates leaving debugging printouts in yourcode. This helps in testing the program but if you are not careful, it may significantly slowdown the final executable because the program will generate debugging strings whether itprints them or not. For example, Fish::Move has a call

DebugPrint(1, "Fish " + oldPos.ToString() + " moves to " + myPos.ToString());

This call concatenates strings and actually calls IntToString multiple times beforeanything moves. A better approach, perhaps, would be to use conditional compilation thatexcludes all debugging code from the final executable. For instance:

#ifdef DEBUG_LEVEL if (DEBUG_LEVEL >= 1) cout << " **** Move::Fish: Fish" << oldPos.ToString() << " moves to " << myPos.ToString() << endl;#endif

In any case, never include debugging statements in your AP exam solutions unlessspecifically instructed to do so.

Normally a low-level module like utils would be reusable: that is, potentially useful inall kinds of projects. This one isn’t — simply because the Sort function depends on theFish class. Bringing utils into another project would drag with it fish, environ, andall the other modules. It would be easy to convert Sort into a templated function thatworks with any data type (See Be Prepared, p. 54). You can try it as an exercise. Notethat you will have to move the templated version of Sort into utils.h and you will haveto add an overloaded < operator for the Fish class.

Page 15: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

Chapter 6. Case Study CS-13

6.4.2. Position

Position is an encapsulated class that represents a position in a two-dimensional gridwith integer coordinates myRow and myCol. It provides a default constructor that builds aposition with coordinates myRow = -1, myCol = -1, another constructor with twoarguments that builds a position with a given row and column, and two accessors, Row()and Col(), that return the respective coordinates.

The Position class also offers four functions, North, South, East, and West, thatbuild and return a new position with row or col appropriately incremented ordecremented by one. These functions support movements of fishes in four possibledirections.

Finally, Position has two “helper” functions, bool Equals andapstring ToString, that are used in the overloaded non-member operators == and <<respectively. ToString is also used for generating debugging printouts.

The << and == operators could be also implemented without helper functions. Forexample:

ostream & operator << (ostream & out, const Position & pos){ out << '(' << pos.Row() << ',' << pos.Col() << ')'; return out;}

55

Assuming that the dimensions of the myWorld matrix are greater than 4 andLEVEL_OF_DEBUG_DETAIL is set to 3, what will be the output from the following code?

Position p(2,3);p.South();DebugPrint(3, "Position: " + p.ToString());

(A) No output(B) **** Position: 2 4(C) **** Position: (2,4)(D) **** Position: (3,3)(E) **** Position: (2,3)

Page 16: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

CS-14 Chapter 6. Case Study

Æ The constructor initializes p’s coordinates to myRow = 2, myCol = 3. You mightexpect the answer D after p.South() presumably increments the row by one. (Note thatToString places myRow and myCol, in this order, inside parentheses and separates themwith a comma.) Unfortunately, the South function is used incorrectly in this code. Southdoes not change its object (in fact South is designated const in the class definition);instead, p.South() builds and returns a new position with the row incremented by one,while p remains unchanged. The correct usage to get the answer D would be

p = p.South();

The answer here is E. Ã

6.4.3. Neighborhood

The class Neighborhood represents a list of positions. The list is stored in an arrayapvector<Position> myList and can hold up to four positions. (Note an unfortunateclash of terms: the list stores elements of the type Position which represent positions ona 2-D grid; at the same time we are used to talking about the “position” of elements in anarray.) The default constructor allocates room for four elements and sets myCount to 0 foran empty list.

The Neighborhood class has the following member functions:

void Add(const Position & pos); // Adds pos to the listPosition Select(int index); // Returns pos stored in the element // numbered by indexint Size(); // Returns the number of elements in the // list

In addition, the ToString function is used for debugging printouts.

Why do we need this class? It has to do with the overall layout of objects in Part 2 of thecase study. A fish needs to know which neighboring positions are vacant in order to makeits next move. The environment knows the locations of all fishes, but this information isprivate. The Neighborhood class provides a way to pass the information about vacantneighboring positions from the environment to a fish.

The name “Neighborhood” may make this class look unnecessarily complicated orspecialized. In fact, the way it is set up has nothing to do with neighbors: it is basically ageneral-purpose class that implements a list. It could be implemented as a reusabletemplated class that could work with any specified number of elements of any type. Suchclasses (known as container classes) are usually included in standard libraries of classes.This one expands on the apvector class: it supports the Add function and keeps track ofhow many elements are actually stored in the list. [ apstack or apqueue couldpotentially do the job here, too, but these are required only for the AB exam. ]

Page 17: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

Chapter 6. Case Study CS-15

6.4.4. Fish and Environment

Things get more complicated as we move on to the higher-level classes. The Fish classand the Environment class are closely dependent on each other. This is to be expected:each fish interacts with its environment. You can see the first sign of this interdependencein the #includes:

// environ.h#include "fish.h"

// environ.cpp#include "environ.h"#include "fish.h"

// fish.cpp#include "fish.h"#include "environ.h"

(Some of these are redundant. Multiple “includes” of the same header file are preventedby using #ifndef conditional compilation directions in each header file. Otherwisefish.h would be included twice in environ.cpp and twice in fish.cpp, causingsyntax errors.)

The case study booklet explores “conversations” between a fish and the environment: whotells whom what and how. Basically, a fish knows that it has to move, if possible, into arandomly-chosen vacant neighboring cell (or stay put if there is nowhere to move). Theenvironment knows which cells around the fish are vacant. The fish obtains thisinformation from the environment and “moves” by updating its own position as storedwithin the fish object. Then it reports to the environment that it has moved so that theenvironment can update itself. We have to keep looking at these two classes togetherbecause they work closely with each other.

We can start by first looking at their data members:

// fish.h

class Fish{ ... int myId; Position myPos; bool amIDefined;};

// environ.h

class Environment{ ... apmatrix<Fish> myWorld; // grid of fish int myFishCreated; // # fish ever created int myFishCount; // # fish in current environment};

Page 18: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

CS-16 Chapter 6. Case Study

As we can see, both are quite limited. A fish is described by its ID tag and its position. Itcan also be defined or undefined. The environment is described by a 2-D array of fishmyWorld, the total number of fish myFishCount, and, for now a bit mysterious,myFishCreated. It is reasonable to assume that myFishCount is the number of fishesin the matrix that are “defined” and that empty cells are designated by “undefined” fishes.This will be confirmed shortly.

The Environment class has one constructor:

Environment(istream & input);

It takes an open input stream (usually a file) as an argument, reads the data from the file,and initializes the environment’s data members. It first reads the number of rows andcolumns in the matrix and resizes myWorld accordingly (from an initially empty matrix).Here we have to pause for a moment and ask ourselves: What is placed into the elements ofmyWorld in the process? There is no explicit initialization, but something happens to thembehind the scenes. Recall that if an apvector or an apmatrix is constructed without anexplicit “fill value” or if it is resized, the new elements are filled with something createdby the element’s default constructor. We have to go to fish.cpp and look at what Fish’sdefault constructor does:

Fish::Fish() : myId(0), amIDefined(false)// postcondition: IsUndefined() == true{}

Sure enough, it places false into the fish’s amIDefined flag. Thus, resize fillsmyWorld with “undefined” fishes.

Environment’s constructor then reads the positions of fishes from the file and adds thesefishes to myWorld:

while (input >> row >> col) AddFish(Position(row, col));

Note how a position is constructed from row, col and passed to AddFish as an argumentin one statement.

While we are at it, we might as well look at the AddFish function (this is the only placewhere it is used):

void Environment::AddFish(const Position & pos){ myFishCreated++; myWorld[pos.Row()][pos.Col()] = Fish(myFishCreated, pos); myFishCount++;}

Page 19: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

Chapter 6. Case Study CS-17

This function creates a fish with a unique ID at the given position and places it intomyWorld:

myWorld[pos.Row()][pos.Col()] = Fish(myFishCreated, pos);

Lots of things happen in this one statement: a fish is created with the given ID and position;the accessor functions Row() and Col() are called for pos and their return values areused as indices into the myWorld array. We can also finally see here howmyFishCreated is used: it is a unique ID value that is incremented before we add a newfish to myWorld. In the case study, myFishCount and myFishCreated always have thesame values after AddFish is done. But suppose in some other model we want to allowfish to die or leave the environment (decrementing myFishCount). Then it is handy tohave two different data members, myFishCount and myFishCreated.

We have to look at the Fish constructor with two arguments in order to understand exactlywhat is added to myWorld:

Fish::Fish(int id, const Position & pos) : myId(id), myPos(pos), amIDefined(true)// postcondition: Location() returns pos, Id() returns id,// IsUndefined() == false{}

In this constructor, the fish is “defined” (amIDefined is set to true) and it gets thespecified ID and position. Note that myPos(pos) uses a copy constructor for thePosition class, which is not explicitly defined; member-by-member copy works for thisclass.

We now continue with the Environment class. It has two accessor functions,NumRows() and NumCols(), that return the dimensions of myWorld. It also hasIsEmpty(pos), which returns true if pos is empty, and a private member functionInRange(pos) that returns true if pos is within the dimensions of myWorld.

A more interesting function is AllFish(): it builds and returns an apvector<Fish>, alist of all defined fishes in the environment. Skipping all the debugging printouts, it lookslike this:

Page 20: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

CS-18 Chapter 6. Case Study

apvector<Fish> Environment::AllFish( ) const// postcondition: returned vector (call it fishList) contains all fish// in top-down, left-right order:// top-left fish in fishList[0],// bottom-right fish in fishList[fishList.length()-1];// # fish in environment is fishList.length(){ apvector<Fish> fishList(myFishCount); int r, c; int count = 0;

for (r = 0; r < NumRows(); r++) for (c = 0; c < NumCols(); c++) if (!myWorld[r][c].IsUndefined()) { fishList[count] = myWorld[r][c]; count++; }

return fishList;}

This function is needed for three reasons: (1) it defines the order of processing the fishesas top-to-bottom, left-to-right; (2) it provides a way of passing a list of all fishes up to theSimulation class and to the Display class without copying the whole myWorld matrix;and (3) it puts all fishes into temporary storage, which prevents processing those fishes thathave already moved in the same step of the simulation. We cannot use myWorld directlyin other classes because it is a private member of Environment. Even if we could, we’dhave to be careful to keep track which fishes had already moved and which hadn’t. Butthis function is expensive: not only does it scan through the whole matrix and builds thelist, it also copies the list when it passes it to the calling function.

All of the above is only background work for the actual simulation — moving the fishes.The actual movement is implemented in three functions:Fish::EmptyNeighbors(...), Fish::Move(...), andEnvironment::Update(...) and this is where things get a bit convoluted. A fishmight know how to swim, but it does not really know its neighbors, so it has to consult itsenvironment, and it has to update the environment after it moves. We have little choice butto pass the environment to the Move function as an argument. The code of Move, strippedof the debugging statements, would look as follows:

Page 21: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

Chapter 6. Case Study CS-19

void Fish::Move(Environment & env)// precondition: Fish stored in env// postcondition: Fish has moved to a new location in env (if possible){ RandGen randomVals; // (See the comment about local variable randomVals in our review // of Part 1)

Neighborhood nbrs = EmptyNeighbors(env, myPos); // Obtain a list of all vacant neighbors of this fish’s position // from env

if (nbrs.Size() > 0) // If there are empty neighbors...

{ Position oldPos = myPos; // Save the old fish’s position

myPos = nbrs.Select(randomVals.RandInt(0, nbrs.Size() - 1)); // Choose one of the neighbors randomly and // make it the new position of this fish. // (It could also be: // myPos = nbrs.Select(randomVals.RandInt(nbrs.Size()); // )

env.Update(oldPos, *this); // Update the position of this fish from oldPos to its // current (new) pos in env }}

The Update function, after we remove redundant checks, might look as follows:

void Environment::Update(const Position & oldLoc, Fish & fish)// precondition: fish was located at oldLoc, has been updated// postcondition: if (fish.Location() != oldLoc) then oldLoc is empty;// Fish fish is updated properly in this environment{ Fish emptyFish; // Make an "undefined" fish

Position newLoc = fish.Location(); // Obtain this fish’s new position (stored in this fish)

myWorld[newLoc.Row()][newLoc.Col()] = fish; // Place this fish into its correct new location in myWorld

if (!(oldLoc == newLoc)) // If this fish indeed moved... myWorld[oldLoc.Row()][oldLoc.Col()] = emptyFish; // Place an undefined fish into this fish’s old location}

(For some reason, the previously used name oldPos suddenly becomes oldLoc in thisfunction in the case study code.) Note the use of !(oldLoc == newLoc) instead of !=.This is because the latter is not overloaded for the Position class. We could get bywithout the comparison altogether if we changed the order of statements:

Page 22: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

CS-20 Chapter 6. Case Study

void Environment::Update(const Position & oldPos, Fish & fish){ Fish emptyFish; myWorld[oldPos.Row()][oldPos.Col()] = emptyFish; Position newPos = fish.Location(); myWorld[newPos.Row()][newPos.Col()] = fish;}

56

Which of the following functions would become less efficient ifapmatrix<Fish> myWorld were eliminated and all defined fishes in the environmentwere stored in a list apvector<Fish> ?

I. bool Environment::IsEmpty(const Position & pos)

II. void Fish::Move(Environment & env)

III. apvector<Fish> Environment::AllFish()

(A) I only(B) II only(C) I and II(D) II and III(E) I, II and III

Æ Without an apmatrix<Fish> myWorld, the function IsEmpty would have to scanthe whole list to find out whether a given position was empty. Even if the list were sortedby position, isEmpty would still need to do a search of some kind (a binary search mightbe a reasonable option). In a matrix representation we can go directly to the given positionin myWorld and see whether the fish there is defined. So IsEmpty becomes lessefficient. Move’s code becomes shorter because it doesn’t have to update the environment,but it calls EmptyNeighbors which calls AddIfEmpty which calls IsEmpty, so itslows down, too. AllFish becomes more efficient, because the list is already there andyou don’t have to scan the whole matrix to build it. The answer is C. Ã

It looks like we have untangled most of this case study! The only little thing that remains is

char Fish::ShowMe() const// postcondition: returns a character that can make me visible{ if (1 <= Id() && Id() <= 26) return 'A' + (Id() - 1);

return '*';}

This function is used for the text-mode display and its code could be moved to the displayfunctions (we have access to a fish’s ID through the Fish::Id() accessor function).ShowMe returns characters 'A' through 'Z' for IDs from 1 to 26 respectively and '*' forany ID greater than 26.

Page 23: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

Chapter 6. Case Study CS-21

6.4.5. Simulation and Display

The Simulation class is trivial: it does not have any data members, its constructor hasno code, and it has only two member functions: one puts an environment through onesimulation step, the other runs a specified number of steps. The Step function obtains alist of all fishes from the environment and then moves each fish. It is the AllFish functionthat defines the order of processing the fishes. If we wanted to process fishes in a differentorder, we would need to sort the list first. The Run function simply calls Step a specifiednumber of times, and it seems redundant. Indeed, main never calls it.

The Simulation class would be more useful if we had different (but related) types ofenvironments, so that we could run simulations on them using the same Simulation class.Here, we could instead just put the Step function inside the Environment class. (Butthen it would no longer represent just an environment; we would have to come up with amore appropriate name.)

The Display class provides a function for displaying all fishes in the given environment.The text display version does not need much of a class: there are no data members, theconstructor is empty, and it has only one function, Show. In the graphics version, theDisplay class may be more involved, but this is not included in the AP exam.

Display is not a friend of Environment (friends are not in the AP subset), so it cannotwork directly with its data members. Instead, the Show function obtains a list of all fishesby calling AllFish. Fortunately, this function already produces the list in the right order,top-to-bottom, left-to-right. If it didn’t, we would have to sort the list (remember theSort function in utils?) before displaying the fishes. In the text display version, thedisplay will be easier to read if you use a printable character (e.g., '.') instead of a spacefor an empty cell.

According to the OOP philosophy, the environment should know how to display itself, so,strictly speaking, the Show function should have been in Environment, not in Display.If we are using graphics, there is the problem that the environment does not know anythingabout the machine’s graphics display capabilities, so it has to depend on the kindness ofstrangers like the Display class. This class may also be convenient if we want toimplement different types of displays for different purposes. For the text-only version, onefree-standing function Show could do the job just as well. (Free-standing functions areconsidered contrary to the OOP spirit. Purists insist that main should be the only free-standing function in any project and that it should consist of one line that constructs one“application” object.)

Page 24: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

CS-22 Chapter 6. Case Study

57

What would be the main advantage of moving the Show function that implements text-modedisplay from the Display class to the Environment class?

(A) The Environment::AllFish function could be eliminated(B) The Fish::ShowMe function could be eliminated(C) The code of Show could be simplified(D) The code of Show could become more efficient for large myWorld matrices(E) It would provide a useful tool for debugging printouts in Fish::Move for large

number of fish

Æ A is false because AllFish is called in Simulation::Step as well. B is alsofalse; while a call to Fish::ShowMe() potentially could be replaced with a call toFish::Id() with the code for converting an integer ID into a display character movedinto Show, this approach can be implemented as easily in Display::Show as inEnvironment::Show. C is true, but the simplification is rather minor. E is not quitetrue: it would provide a tool for debugging printouts, but this tool won’t be very usefulbecause it would generate too much output.

In D, a call to AllFish will become unnecessary because we could work directly with themyWorld matrix. In the original implementation we run a nested loop through all rows andcolumns three times on each step: once to form a list of all fish in Simulation::Step,second to form a list of all fish in Display::Show, and third to display each fish. In themodified design we will need to run it only twice, which may result in better performance.The answer is D. Ã

6.4.6. main

The main program opens a data file and creates an environment from it. It does not checkwhether it opened the data file successfully or not; if it cannot find the file, then theenvironment’s constructor reports an error message and aborts the program. Then maincreates a simulation object, prompts the user to enter a desired number of steps, and runsthe simulation through these steps, displaying the environment after each step. The programreads a dummy string to rid the input stream of pending new line characters and to pausethe display after each step.

Page 25: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

Chapter 6. Case Study CS-23

6.5. Appendix: Doing It From Scratch?

The case study discusses many subtle design decisions and options by asking questionssuch as “Does the EmptyNeighbors function belong in the Fish class (where it isactually placed) or in the Environment class?” or “Is the Simulation classnecessary?” But it never really addresses the basic question: Why do we need sevenclasses, nine modules, and 25 pages (over 1350 lines) of code to implement what isessentially the rather simple task of repeatedly moving some elements in a 2-D array torandomly-chosen vacant neighboring positions? Could a simpler implementation with, say,one class and far less code do the job?

The main reason for this complex structure, with intertwined Fish and Environmentclasses and the additional Neighborhood class, is the OOP philosophy of smart objects.If we had several different types of fish or sea creatures in the same environment, thendifferent creatures could be represented by different but related classes arranged in thesame hierarchy. A member function with the same name, (e.g. Move or Swim) in each ofthese classes could implement “swimming” for this particular type of fish. Some couldcrawl and others could fly. The myWorld matrix would contain pointers to different typesof fish and the right function would be called for each type of fish automatically. This ispossible in C++ due to a feature known as virtual functions and polymorphism (not in theAP subset).

But in a simple case, our life would be much easier if some objects were just plain dumband were told what to do and how to do it. For this particular simulation, OOP is overkill.No matter what the theory says, it is easier to design, write, debug, understand, maintain,and expand a program that uses one class with 200 lines of code than seven classes with1300 lines.

Exercise 8 on page 42 in the case study booklet asks: What are the advantages anddisadvantages of designing and implementing your own code, as opposed to understandingand adapting the existing code? It depends, of course, on the quality of the code, whetherthere are any problems with it (e.g., it runs too slowly or it cannot be adapted to supportnew features), and on your software design and programming experience. In industry thisquestion may be also decided according to the policies (and politics) of a givenorganization.

You may be tempted to give it a shot and rewrite the whole thing. If you do, verify thatyour program produces exactly the same result as the case study program (when you seedthe random number generator with the same seed). If you accomplish that, you can say thatyou have completely understood the case study code. If you don’t want to do your owndesign, you can use the seamain.cpp and seafish.h provided here as a starting pointand write your own seafish.cpp. Or see our seafish.cpp which completes theproject.

Page 26: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

// seamain.cpp

#include <iostream.h>#include <fstream.h>#include "apstring.h"#include "seafish.h"

void Show(const SeaFish &model);

int main(){ apstring filename; int step, numSteps;

cout << "Data file name: "; getline(cin, filename);

#ifdef _MSC_VER// Use the nocreate flag For VC++ to prevent creating an empty file// when fish.dat is not found: ifstream file(filename.c_str(), ios::nocreate);#else ifstream file(filename.c_str());#endif

if (!file) { cout << "Cannot open " << filename << endl; return 1; }

SeaFish model(file); cout << "Start:\n"; Show(model);

cout << "Number of steps: "; cin >> numSteps; cin.ignore(1000, '\n');

for (step = 1; step <= numSteps; step++) { model.Step(); cout << "After step " << step << ":\n"; Show(model); cout << "Press <Enter> to continue...\n"; cin.ignore(1000, '\n'); } return 0;}

//****************************************************************

Page 27: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

void Show(const SeaFish &model){ int rows = model.NumRows(); int cols = model.NumCols(); int row, col; Fish fish; char ch;

cout << endl; for (row = 0; row < rows; row++) { for (col = 0; col < cols; col++) { fish = model.GetFish(row, col); if (fish.state == EMPTY) ch = '.'; else if (fish.id > 26) ch = '*'; else ch = 'A' + fish.id - 1; cout << ch; } cout << endl; } cout << endl;}

Page 28: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

// seafish.h

#ifndef _SEAFISH_H#define _SEAFISH_H

#include <iostream.h>#include <apmatrix.h>

enum STATE {EMPTY, ALIVE, MOVED};

struct Fish{ int id; STATE state;

Fish(); Fish(int anyID);};

class SeaFish

{ public:

SeaFish(istream &input, bool randomSeed = true);

int NumRows() const; int NumCols() const; Fish GetFish(int row, int col) const; void Step(); // Move all fishes

private:

bool InRange(int row, int col) const; bool IsEmpty(int row, int col) const; void Move(int row, int col); // Move the fish at row, col

apmatrix<Fish> myWorld; int myFishCreated;};

#endif

Page 29: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

// seafish.cpp

#include <time.h> // for time()#include <stdlib.h> // for rand/srand#include "seafish.h"

int RandomInt(int n){ return int(rand() / (double(RAND_MAX) + 1) * n);}

//****************************************************************

Fish::Fish() : id(0), state(EMPTY){}

Fish::Fish(int anyID) : id(anyID), state(ALIVE){}

//****************************************************************

SeaFish::SeaFish(istream &input, bool randomSeed) : myFishCreated(0), myWorld(0,0){ int rows, cols, row, col;

input >> rows >> cols; myWorld.resize(rows, cols);

while (input >> row >> col) { myFishCreated++; myWorld[row][col] = Fish(myFishCreated); }

if (randomSeed) srand(unsigned(time(0))); // Seed random number generator // from system time}

int SeaFish::NumRows() const{ return myWorld.numrows();}

int SeaFish::NumCols() const{ return myWorld.numcols();}

bool SeaFish::InRange(int row, int col) const{ return 0 <= row && row < NumRows() && 0 <= col && col < NumCols();}

bool SeaFish::IsEmpty(int row, int col) const{ return InRange(row, col) && myWorld[row][col].state == EMPTY;}

Fish SeaFish::GetFish(int row, int col) const{ return myWorld[row][col];}

Page 30: Be Prepared AP - Com Sci Gate · 2010. 7. 18. · CS-2 Chapter 6. Case Study 6.1. Introduction The Case Study is a component of AP CS exams that is based on a complete small software

void SeaFish::Move(int row, int col){ apmatrix<int> neighbor(2,4); // Holds positions of empty neighbors int n, count = 0; int newRow, newCol; Fish emptyFish;

// Examine four neighbors and collect empty neighbors:

if (IsEmpty(row-1, col)) // North { neighbor[0][count] = row-1; neighbor[1][count] = col; count++; } if (IsEmpty(row+1, col)) // South { neighbor[0][count] = row+1; neighbor[1][count] = col; count++; } if (IsEmpty(row, col+1)) // East { neighbor[0][count] = row; neighbor[1][count] = col+1; count++; } if (IsEmpty(row, col-1)) // West { neighbor[0][count] = row; neighbor[1][count] = col-1; count++; }

// Move fish to a randomly selected empty neighbor: if (count > 0) { n = RandomInt(count);

// Better (but would produce a result different from the case study):// if (count > 1) n = RandomInt(count);// else n = 0;

newRow = neighbor[0][n]; newCol = neighbor[1][n]; myWorld[newRow][newCol] = myWorld[row][col]; myWorld[newRow][newCol].state = MOVED; myWorld[row][col] = emptyFish; }}

void SeaFish::Step(){ int row, col;

// Move all fishes: for (row = 0; row < NumRows(); row++) for (col = 0; col < NumCols(); col++) if (myWorld[row][col].state == ALIVE) Move(row, col);

// Restore the state of all moved fishes to ALIVE: for (row = 0; row < NumRows(); row++) for (col = 0; col < NumCols(); col++) if (myWorld[row][col].state == MOVED) myWorld[row][col].state = ALIVE;}