/* A sample object oriented program for Conway's Game of Life using C++ File: life.cc Date: Sun Nov 6 12:22:13 PST 1994 Author: Richard J Botting */ /* PROBLEM A large rectangular grid of cells (the board)evolves thru applying the same simple rule again and again to every cell in the grid at the same time. Each cell is either alive or dead. In each cycle, all cells count the number of cells alive in the 8 surrounding cells and then the central sell comes alive or dies according to these rules Old State Count New State dead 3 alive dead not 3 dead alive 2,3 alive alive else dead All cells make this decision at the same time and then change. Write a simple program to help somebody play the game. /* ANALYSIS The natural classes in this project are cell_state, cell, board, and perhaps users because they are nouns in the spec and refer to identifiable entities. Now in a simple problem the user doesn't have a very interesting history and only occurs once per program. Hence the user does not need to be a class or a data type. Perhaps it will be modelled by the main fucntion instead. Therefore we have to think in more detail about cell-state cell board Refinement: cell_state Two values alive and dead, // more a type than a class cell Has a cell_state identified by line and row in board initially dead can come alive can die may be seen to be alive or dead // definitely a class board Has boundaries and many cells identified by the time it occurs change state of cell (if inside the boundary) can find state of cell (assumed dead on or outside boundary) can count the number of alive neighbors(inside!) (The above let other functions forget about the boundary) can change according to the rules of Life can be copied from another board (=) can be compared with another board can be input by the user can be shown to the user can be filled with random patterns(perhaps?) can be saved in a file(later prototype) can be loaded from a file(later prototype) // definitely a class The remaining entity (the user) is best modelled by the main function...unless you want a multi-user life-game server. Note. The idea of a nieghbor or a boundary can not exist except in the context of a board... So I've associated neighbors with board not cell. It follows that the board knows when a row and column is a cell but a cell does not (being a cell means it is in the board!). Hence the board will be able to check array bounds, but cell will not. Decision: it might simplify maintenance to separate out a model of the cells and boards as viewed by the user but I chose not to. Decision: I could save space by coding both the current value and the next value into a single cell. This takes more time and moves away from the goal of showing a simple OO design. Decision: I could have a dynamic list of cells that are about to be alive instead of a second board. This may be faster and save storage. It complicates the solution. */ #include #include #include //Small board to allow simple testing #define LINES 9 #define COLS 9 /* Following are more typical #define LINES 23 #define COLS 78 */ enum cellstate{ dead, alive } ; //C++ simplifies the definition of types char outmap[]={'.', 'X'}; //Converts internal cell state to the users //view of the state // Why? laziness and amendability class cell { private: cellstate mystate; public: cell(){ mystate=dead; }// initially dead void born(){mystate=alive; }// can come alive void die(){mystate=dead; }// can die cellstate state()const{return mystate%2;}// alive or dead // a const function will not change the // state of it's object // A cell can be made to do nothing but the above // four things. };//end cell class board { private: cell b[LINES][COLS]; int inside(int r, int c)const { return 0>(istream& s, board &b); //can be input by the user //can be filled with random patterns(perhaps?) //can be saved in a file(later prototype) //can be loaded from a file(later prototype) };//end board // A useful utility function int more() { int ch; cout<<"More?[Y/N] ";flush(cout); while((ch=getchar())!='\n' && ch!='Y' && ch!='y' && ch!='n' && ch!='N' && ch!=EOF); return(ch=='\n' || ch=='Y' || ch=='y'); } int main() { board b[2]; board *newb=&b[0], *oldb=&b[1], *t; cin >> *oldb; system("clear"); cout<< *oldb; while(more()) { (*oldb).next(*newb); system("clear"); cout<< *oldb; t=newb; newb=oldb; oldb=t; } exit(0); } ostream& operator<<(ostream& s, board b) { int r,c; for(c=0;c>(istream& s, board &b) { int r,c; char ch; cout <<"\nInput a board("<