// File: ex7-16.cpp #include #include using namespace std; enum Bool { FALSE, TRUE}; enum LifeForm {VACANT, WEED, RABBIT, HAWK}; const int GridSize = 10; const int Cycles = 10; const int NumberLifeForms = 4; const int HawkLifeExpectancy = 8; const int HawkOvercrowdingLimit = 3; const int RabbitLifeExpectancy = 3; class Grid; class LivingThing { protected: int x,y; void AssessNeighborhood(const Grid& G, int sm[]); public: LivingThing(int _x, int _y): x(_x), y(_y) {} virtual ~LivingThing() {} virtual LifeForm WhoAmI() const = 0; virtual LivingThing* next(const Grid& G) = 0; }; class Grid { private: LivingThing* cell[GridSize][GridSize]; public: Grid(); ~Grid() { if (cell[1][1]) release(); } void update(Grid&); void release(); void print(); LivingThing* get_cell(int row, int col) const; }; /* This function counts the number of each LivingThing thing in the neighborhood. A neighborhood is a square and the 8 adjacent squares on each side of it */ void LivingThing::AssessNeighborhood(const Grid& G, int count[]) { int i, j; count[VACANT] = count[WEED] = count[RABBIT] = count[HAWK] = 0; for (i = -1; i <= 1; ++i) for (j = -1; j <= 1; ++j) count[G.get_cell(x+i,y+j) -> WhoAmI()]++; } LivingThing* Grid::get_cell(int row, int col) const { return cell[row][col]; } class Vacant : public LivingThing { public: Vacant(int _x, int _y):LivingThing(_x,_y) {} LifeForm WhoAmI() const { return (VACANT); } LivingThing* next(const Grid& G); }; class Weed : public LivingThing { public: Weed(int _x, int _y): LivingThing(_x,_y) {} LifeForm WhoAmI() const { return (WEED); } LivingThing* next(const Grid& G); }; class Rabbit : public LivingThing { protected: int age; public: Rabbit(int x, int y, int a = 0) : LivingThing(x,y), age(a) {} LifeForm WhoAmI() const { return (RABBIT); } LivingThing* next(const Grid& G); }; class Hawk : public LivingThing { protected: int age; public: Hawk(int x, int y, int a = 0): LivingThing(x,y), age(a) {} LifeForm WhoAmI() const { return (HAWK); } LivingThing* next(const Grid& G); }; // This function determines what will be in an Vacant square in the next cycle LivingThing* Vacant::next(const Grid& G) { int count[NumberLifeForms]; AssessNeighborhood(G,count); // If there is more than one Rabbit in the neighborhood, a new Rabbit // is born. if (count[RABBIT] > 1) return (new Rabbit(x,y)); // otherwise, if there is more than one Hawk, a Hawk will be born else if (count[HAWK] > 1) return (new Hawk(x, y)); // otherwise, if there is Weed in the neighborhood, Weed will grow else if (count[WEED]) return (new Weed(x, y)); // otherwise the square will remain Vacant else return (new Vacant(x, y)); } // if there is more Weeds than Rabbits, then new Weed will grow, // otherwise Vacant LivingThing* Weed::next(const Grid& G) { int count[NumberLifeForms]; AssessNeighborhood(G, count); if (count[WEED] > count[RABBIT]) return (new Weed(x, y)); else return (new Vacant(x, y)); } /* The Rabbit dies if: there's more Hawks in the neighborhood than Rabbits not enough to eat or if it's too old otherwise a new Rabbit is born */ LivingThing* Rabbit::next(const Grid& G) { int count[NumberLifeForms]; AssessNeighborhood(G, count); if (count[HAWK] >= count[RABBIT] ) return (new Vacant(x, y)); else if (count[RABBIT] > count[WEED]) return (new Vacant(x, y)); else if (age > RabbitLifeExpectancy) return (new Vacant(x, y)); else return (new Rabbit(x,y, age + 1)); } // Hawk die of overcrowding, starvation, or old age LivingThing* Hawk::next(const Grid& G) { int count[NumberLifeForms]; AssessNeighborhood(G, count); if (count[HAWK] > HawkOvercrowdingLimit) return (new Vacant(x, y)); else if (count[RABBIT] < 1) return (new Vacant(x,y)); else if (age > HawkLifeExpectancy) return (new Vacant (x, y)); else return (new Hawk(x, y, age + 1)); } Grid::Grid() { LifeForm creature; int i, j; for (i = 0; i < GridSize; i++) for (j = 0; j < GridSize; j++) { if (i == 0 || i == GridSize - 1 || j ==0 || j == GridSize - 1) creature = VACANT; else creature = LifeForm(rand() % NumberLifeForms); switch (creature) { case HAWK: cell[i][j] = new Hawk(i,j); break; case RABBIT: cell[i][j] = new Rabbit(i,j); break; case WEED: cell[i][j] = new Weed(i,j); break; case VACANT: cell[i][j] = new Vacant(i,j); } } } void Grid::release() { int i, j; for (i = 1; i < GridSize - 1; ++i) for (j = 1; j < GridSize - 1; ++j) delete cell[i][j]; cell[1][1] = 0; } void Grid::update(Grid& old) { int i, j; for (i = 1; i < GridSize - 1; ++i) for (j = 1; j < GridSize - 1; ++j) cell[i][j] = old.cell[i][j] -> next(old); } void Grid::print() { LifeForm creature; int i, j; for (i = 1; i < GridSize - 1; i++) { for (j = 1; j < GridSize - 1; j++) { creature = cell[i][j]->WhoAmI(); switch (creature) { case HAWK: cout << "H"; break; case RABBIT: cout << "R"; break; case WEED: cout << "W"; break; case VACANT: cout << "0"; } } cout << endl; } cout << endl; } int main() { Grid G1, G2; G1.print(); for (int i = 1; i <= Cycles; i++) { cout << "Cycle " << i << endl; if (i % 2) { G2.update(G1); G2.print(); G1.release(); } else { G1.update(G2); G1.print(); G2.release(); } } }