00001 #include "macros.h"
00002 #include <string>
00003 #include <iostream>
00004 using namespace std;
00005 #include "AbstractExercise.h"
00006 #include <ctime>
00007 #include <cstdlib>
00008
00009
00010 namespace {
00011 const int SIZE_X = 30;
00012 const int SIZE_Y = 20;
00013 const char ALIVE = '*';
00014 const char DEAD = ' ';
00015 typedef char lifeMatrix_t[SIZE_X][SIZE_Y];
00016 }
00017
00023 class ModN {
00024 public:
00025
00030 ModN(int mod, int value = 0) : fMod(mod), fValue(value), fCompleted(false) {}
00031
00036 inline ModN& operator++(int) {
00037 fValue = (fValue + 1) % fMod;
00038 fCompleted = (fValue == 0);
00039 return *this;
00040 }
00041
00046 inline ModN& operator--(int) {
00047 fValue = (fValue + fMod - 1) % fMod;
00048 fCompleted = (fValue == fMod - 1);
00049 return *this;
00050 }
00051
00056 inline bool operator==(const ModN& operand) const { return (fMod == operand.fMod) && (fValue == operand.fValue); }
00057
00066 inline operator int() const { return fValue; }
00067
00074 inline bool completed() { return fCompleted; }
00075 private:
00076 int fMod;
00077 int fValue;
00078 bool fCompleted;
00079 };
00080
00085 class LifeMatrix {
00086 public:
00090 inline void display() const {
00091 for(int i = 0; i<SIZE_Y; i++) {
00092 cout << "|";
00093 for(int j = 0; j<SIZE_X; j++){
00094 cout << fMatrix[j][i];
00095 }
00096 cout << "|";
00097 cout << endl;
00098 }
00099 cout << endl;
00100 }
00101
00108 inline int countNeighbours (const ModN& x, const ModN& y) const {
00109 int neighbours = 0;
00110
00111 ModN mX = x;
00112 mX--;
00113 for(int i = 0; i<3; i++){
00114 ModN mY = y;
00115 mY--;
00116 for(int j = 0; j<3; j++){
00117 neighbours += !((mX == x)&&(mY == y)) && isAlive(mX, mY) ? 1 : 0;
00118 mY++;
00119 }
00120 mX++;
00121 }
00122 return neighbours;
00123 }
00124
00129 inline void fill(){
00130 for(int i = 0; i<SIZE_X; i++){
00131 for(int j = 0; j<SIZE_Y; j++){
00132 fMatrix[i][j] = fillGlider(i, j);
00133 }
00134 }
00135 }
00136
00142 inline void kill(const ModN& i, const ModN& j){
00143 fMatrix[i][j] = DEAD;
00144 }
00145
00151 inline void enliven(const ModN& x, const ModN& y){
00152 fMatrix[x][y] = ALIVE;
00153 }
00154
00160 inline bool isAlive(const ModN& x, const ModN& y) const {
00161 return fMatrix[x][y] == ALIVE;
00162 }
00163
00167 static inline void initRand() {
00168 long sek;
00169 time(&sek);
00170 srand((unsigned)sek);
00171 }
00172
00173 private:
00174
00178 inline char fillRand(int x, int y) {
00179 return rand()%2 ? ALIVE : DEAD;
00180 }
00181
00185 inline char fillSquare58(int x, int y){
00186 return (x>5)&&(x<8)&&(y>5)&&(y<8) ? ALIVE : DEAD;
00187 }
00188
00192 inline char fillLine(int x, int y){
00193 return (x==8 || x== 12)&&(y>5)&&(y<9) ? ALIVE : DEAD;
00194 }
00195
00199 inline char fillGlider(int x, int y){
00200 return
00201 (x==0 && y== 0)
00202 ||(x==0 && y== 1)
00203 ||(x==0 && y== 2)
00204 ||(x==1 && y== 0)
00205 ||(x==2 && y== 1)
00206 ? ALIVE : DEAD;
00207 }
00208
00209 lifeMatrix_t fMatrix;
00210 };
00211
00216 class Life {
00217 public:
00218 Life() : fNow(new LifeMatrix()), fFuture(new LifeMatrix()) {}
00219
00223 inline void run(){
00224 LifeMatrix::initRand();
00225 fill();
00226 while(true){
00227 display();
00228 calculate();
00229 wait();
00230 }
00231 }
00232
00233 ~Life(){
00234 delete fNow;
00235 delete fFuture;
00236 }
00237 private:
00238
00242 inline void Life::fill(){
00243 fNow->fill();
00244 }
00245
00249 inline void Life::display(){
00250 cls();
00251 fNow->display();
00252 }
00253
00261 inline void calculate(){
00262 for(ModN i(SIZE_X, 0); !i.completed(); i++){
00263 for(ModN j(SIZE_Y, 0); !j.completed(); j++){
00264 int n = fNow->countNeighbours(i, j);
00265 if((n < 2)||(n > 3)){
00266 fFuture->kill(i, j);
00267 } else if ((n == 2) && (fNow->isAlive(i, j))) {
00268 fFuture->enliven(i, j);
00269 } else if (n == 3){
00270 fFuture->enliven(i, j);
00271 } else {
00272 fFuture->kill(i, j);
00273 }
00274 }
00275 }
00276 swap();
00277 }
00278
00282 inline void Life::swap(){
00283 LifeMatrix* tmp = fNow;
00284 fNow = fFuture;
00285 fFuture = tmp;
00286 }
00287
00291 static inline void Life::wait() {
00292 for(long i= 0;i<19999999L;i++){}
00293 }
00294
00298 static inline void Life::cls(){
00299 system("cls");
00300 }
00301
00302 LifeMatrix* fNow;
00303 LifeMatrix* fFuture;
00304 };
00305
00310 class LifeExercise : public AbstractExercise {
00311 public:
00312
00313 LifeExercise(string name) : AbstractExercise(name){}
00314
00315 protected:
00316
00317 void execute();
00318
00319 private:
00320 Life fLife;
00321 };
00322
00323 namespace {
00324 LifeExercise proto("LifeExercise");
00325 }
00326
00327 void LifeExercise::execute(){
00328 fLife.run();
00329 }
00330
00331