#include #include #include using namespace std; ////////////////////// // Global constants // Starfish related // the biggest size a starfish can reach const int maxsize = 5; // the size a starfish is when it can first breed const int breedsize = 3; // Plot related // the maximum number of barnacles in a plot const int maxbarnacles = 10; // Seashore related const int seashoresize = 10; const int breedingperiod = 10; // end Global constants ////////////////////// ////////////////////// // Function Prototypes int RandomNumber(int, int); ////////////////////// // StarfishGraph class class StarfishGraph{ public: StarfishGraph(int screenwidth = 73); void addPoint(int,int); void graph(); private: vector barnacles; vector starfish; int screenwidth; }; // Not much to do here StarfishGraph::StarfishGraph(int screen){ screenwidth = screen; } void StarfishGraph::addPoint(int barn, int star){ // add entries to the vectors barnacles.push_back(barn); starfish.push_back(star); } void StarfishGraph::graph(){ // find the largest element to set the scale int biggest = 0; for (int i = 0; i < barnacles.size(); i++){ if (barnacles[i] > biggest) biggest = barnacles[i]; if (starfish[i] > biggest) biggest = starfish[i]; } // now that we know the biggest, set the scale float scale = (float) screenwidth / biggest; // output the header line cout <<"Time" << setw(45) << "[Barnacle = b Starfish = * Points Cross = +]" << endl; // now go through the vectors and print out the positions // of the starfish and barnacles int starpos, barnpos; for (int i = 0; i < starfish.size(); i++){ cout << setw(4) << i << "|"; starpos = static_cast (starfish[i] * scale); barnpos = static_cast (barnacles[i] * scale); for (int x = 0; x <= screenwidth; x++){ if (starpos != barnpos){ if (x == starpos) cout << "*"; else if (x == barnpos) cout << "b"; else cout << " "; } else { if (x == starpos) cout << "+"; else cout << " "; } } cout << endl; } // Now output the bottom scale cout << " "; for (int i = 0; i < screenwidth; i++) if (i % 5 == 0) cout << "+"; else cout <<"-"; cout << endl; for (int i = 0; i < screenwidth; i++) if ((i % 5 == 0)||(i == 0)) cout << setw(5) << (int) (i / scale); cout << endl; } // end Graph class ////////////////////// ////////////////////// // Starfish Class Definition class Starfish{ public: Starfish(); int getSize(); void grow(); void feed(); bool starve(); int breed(); Starfish *getNextStarfish(); void setNextStarfish(Starfish *); private: int size; bool eaten; Starfish *nextStarfish; }; // Starfish start with size 1 and have eaten Starfish::Starfish(){ size = 1; eaten = true; nextStarfish = NULL; } // return the current size of the starfish int Starfish::getSize(){ return size; } // If the starfish is not as large as it can get // then it grows void Starfish::grow(){ if (size < maxsize) size++; } // If the starfish gets to feed, // then it has eaten void Starfish::feed(){ eaten = true; } // This method checks to see if the seafish // dies of starvation. If it has eaten, then it // doesn not die, but no longer has eaten. If it // has not eaten, then it dies. This function returns // true if the starfish starves to death. bool Starfish::starve(){ if (!eaten) return true; else { eaten = false; return false; } } // If the starfish is of breeding size // and has eaten, then it can breed // It produces a random number of larva // between zero and its own size. The // number of larva is returned. Zero is // a value because some larva get eaten. int Starfish::breed(){ if ((size >= breedsize) && eaten) { return RandomNumber(0,size); } else return 0; } // Returns the next Starfish Starfish *Starfish::getNextStarfish(){ return nextStarfish; } // Sets the next starfish void Starfish::setNextStarfish(Starfish *next){ nextStarfish = next; } // end Starfish Class ////////////////////// ////////////////////// // Plot Class Definition class Plot{ public: Plot(); Starfish *advanceTime(); void addStarfish(Starfish *); int getNumStarfish(); int getNumBarnacles(); int spawnStarfish(); ~Plot(); private: // private variables int barnacles; Starfish *starfishes; }; // Constructor // Plots start off full of barnacles // and empty of starfish Plot::Plot(){ barnacles = maxbarnacles; starfishes = NULL; }; // In each time unit, Starfish will eat barnacles. // Each starfish will eat one barancle. // Starfish eat in the order they arrived. // Starfish that get to eat grow. // Starfish that do not get to eat are returned on a list. // If there is at least one barnacle, another will grow // If there are no barnacles, none will grow if there are any // starfish present, otherwise one will grow. Starfish * Plot::advanceTime(){ Starfish * currentStarfish = starfishes; Starfish * lastStarfish = NULL; // if there are no barnacles, all the starfishes go if (0 == barnacles) { starfishes = NULL; } else { // there are some barnacles to eat // First, the starfish eat the barnacles one at // a time while ((barnacles > 0) && (currentStarfish != NULL)){ lastStarfish = currentStarfish; barnacles --; currentStarfish->feed(); currentStarfish->grow(); currentStarfish = currentStarfish->getNextStarfish(); } // now check to see if the starfish ate all the barnacles // if so, clip the list of starfish at the last one that // ate, and return the rest of the list if ((0 == barnacles) && (currentStarfish != NULL)){ if (lastStarfish != NULL) lastStarfish->setNextStarfish(NULL); } } // Now grow the barnacles so the starfish can eat next time // barnacles grow if there is already one there if (barnacles > 0){ if (barnacles < maxbarnacles) barnacles ++; } else { // or if there are no starfish if ((0 == barnacles) && (getNumStarfish() == 0)){ if (barnacles < maxbarnacles) barnacles ++; } } return currentStarfish; }; // Add a starfish to the plot. Best to add it // at the end of the list void Plot::addStarfish(Starfish * newstarfish){ Starfish * currentStarfish = starfishes; if (starfishes == NULL){ starfishes = newstarfish; } else { // go to the end of the list while (currentStarfish->getNextStarfish() != NULL){ currentStarfish = currentStarfish->getNextStarfish(); } // now add the new starfish to the list currentStarfish->setNextStarfish(newstarfish); } }; // returns the number of starfish in the plot int Plot::getNumStarfish(){ int numStarfish = 0; Starfish *currentStarfish = starfishes; while (currentStarfish != NULL){ numStarfish++; currentStarfish = currentStarfish->getNextStarfish(); } return numStarfish; }; // returns the number of barnacles in the plot int Plot::getNumBarnacles(){ return barnacles; }; // go through the list of starfish // breed each one and return the total // larva produced int Plot::spawnStarfish(){ int total = 0; Starfish *currentStarfish = starfishes; while (currentStarfish != NULL){ total += currentStarfish->breed(); currentStarfish = currentStarfish->getNextStarfish(); } return total; }; // Need to define a destructor to clean up the // list of Starfish Plot::~Plot(){ Starfish * currentStarfish = starfishes; while (starfishes != NULL){ currentStarfish = starfishes; starfishes = starfishes->getNextStarfish(); delete currentStarfish; } } // end Plot Class Definition ////////////////////// ////////////////////// // Seashore Class Definition class Seashore{ public: Seashore(); void advanceTime(); int getTime(); int totalBarnacles(); int totalStarfish(); void seedStarfish(int); private: int time; vector shoreline; }; // Default constructor // set the initial size and vector size Seashore::Seashore(){ time = 0; shoreline.resize(seashoresize); }; //return the simulation time int Seashore::getTime(){ return time; } // For each time unit on the seashore // Go through the vector of plots // For each plot // -advance time // - if it is time to spawn, spawn each plot and count larva // -go through the list that is returned // and see if each starfish starves. // - if it doesn't, it moves up or down one plot randomly // Spawn the new starfish by calling seedStarfish. void Seashore::advanceTime(){ int newplace; int newStarfishes = 0; Starfish *leftoverStarfish, *nextStarfish; bool timetospawn = false; time ++; if ((time % breedingperiod) == 0) timetospawn = true; for (int i = 0; i < shoreline.size(); i++){ leftoverStarfish = shoreline[i].advanceTime(); if (timetospawn) newStarfishes += shoreline[i].spawnStarfish(); while (leftoverStarfish != NULL){ nextStarfish = leftoverStarfish->getNextStarfish(); // Unclip the first starfish from the rest of the lift // This is important! leftoverStarfish->setNextStarfish(NULL); if (!leftoverStarfish->starve()){ // choose up or down // 0 is down, 1 up // newplace is the new plot number if (RandomNumber(0,1)){ //move down if (0 == i) newplace = shoreline.size() - 1; else newplace = i - 1; } else { // move up if ((shoreline.size() - 1) == i) newplace = 0; else newplace = i + 1; } // move the starfish now that we know where it goes shoreline[newplace].addStarfish(leftoverStarfish); } else{// darwin wins, starfish loses delete (leftoverStarfish); } leftoverStarfish = nextStarfish; }// end while }// end for i loop if (timetospawn) seedStarfish(newStarfishes); }; // returns the total number of barnacles on the seashore int Seashore::totalBarnacles(){ int total = 0; for (int i = 0; i < shoreline.size(); i++){ total += shoreline[i].getNumBarnacles(); } return total; }; // returns the total number of barnacles on the seashore int Seashore::totalStarfish(){ int total = 0; for (int i = 0; i < shoreline.size(); i++){ total += shoreline[i].getNumStarfish(); } return total; }; // Allow starfish to be added to the shoreline void Seashore::seedStarfish(int numLarva){ Starfish * newStarfish; int whichPlot; for (int i = 0; i < numLarva; i++){ whichPlot = RandomNumber(0,shoreline.size()-1); newStarfish = new(Starfish); shoreline[whichPlot].addStarfish(newStarfish); } } // end Seashore Class Definition ////////////////////// ////////////////////// // Seashore Simulation Class Definition class Seashore_sim{ public: Seashore_sim(); void run(int); private: Seashore theseashore; StarfishGraph results; }; Seashore_sim::Seashore_sim(){ } // Run the simulation by advancing time a number of times, and // record the number of starfish and barnacles each time void Seashore_sim::run(int maxtime){ int numBarnacles; int numStarfish; cout << setw(8) << "Time" << setw(15) << "Barnacles" << setw(15) << "Starfish" << endl; cout << setw(8) << "----" << setw(15) << "---------" << setw(15) << "--------" << endl; theseashore.seedStarfish(1); for (int i = 1; i <= maxtime; i++){ theseashore.advanceTime(); numBarnacles = theseashore.totalBarnacles(); numStarfish = theseashore.totalStarfish(); cout << setw(8) << theseashore.getTime() << setw(15) << numBarnacles << setw(15) << numStarfish << endl; results.addPoint(numBarnacles,numStarfish); } cout << endl << endl; results.graph(); } // ////////////////////// ////////////////////// // Main function int main(){ // seed the random number generator long ltime = time(NULL); int stime = (unsigned) ltime/2; srand(stime); //start the simulation Seashore_sim simulation; simulation.run(100); return 0; } // ////////////////////// ////////////////////// // Function declarations int RandomNumber(int lowest, int highest){ int bin = 0; int numPossResults = highest - lowest + 1; int portion = 10000/numPossResults; int intermediate = (int) (((float) rand()/RAND_MAX) * (10000)); while ((intermediate - portion) > 0){ intermediate -= portion; bin++; } return bin + lowest; }