Dal C al C++/Gioco life di Conway
Wikibooks, manuali e libri di testo liberi.
Di seguito il listato in C++ per un'implementazione testuale del gioco della vita.
Wikipedia contiene una voce riguardante Gioco della vita
Paradigmi utilizzati:
// Author: BlakWolf, © 2004 // Released under GPL v.2 or later, at your option #include <iostream> #include <cstdlib> #include <vector> #include <set> using std::cout; using std::cin; using std::dec; using std::hex; // Osservabile e osservato contemporaneamente, gestisce le regole "biologiche" class Casella{ public: enum stato{vuoto=0,pieno}; typedef std::set<Casella *> Container; typedef Container::iterator Iterator; private: stato stato_; int vicini_futuri; int vicini; Container osservatori; public: Casella( const Casella::stato & s = Casella::vuoto ) : stato_(s), vicini_futuri(0), vicini(0){} //non copia gli osservatori Casella(const Casella& c): vicini(c.vicini), vicini_futuri(c.vicini_futuri), stato_(c.stato_){} virtual ~Casella(){} // Registra gli osservatori a cui notificare i cambiamenti inline void Registra(Casella& c) { if (&c != this){ osservatori.insert(&c); } } inline void Imposta(const Casella::stato& s){ stato_=s; } inline void Muori(){ if(stato_==pieno){ Imposta(Casella::vuoto); Notifica(-1); } } inline void Nasci() { if (stato_==vuoto){ Imposta(Casella::pieno); Notifica(1); } } // Aggiorna inline void Ciclo() { vicini=vicini_futuri; } // Regole del gioco inline void Verifica() { if (stato_==pieno){ if (vicini<2 || vicini>3) // Modificare questa riga per cambiare le regole di morte Muori(); }else { if (vicini==3) // Modificare questa riga per cambiare le regole di nascita Nasci(); } } inline bool Leggi() const{ return stato_==pieno; } private: // Notifica ai vicini nascita o morte inline void Notifica(int msg) const{ for (Iterator it = osservatori.begin(); it != osservatori.end(); ++it){ (*it)->RiceviNotifica(msg); } } // Ricevi la notifica dai vicini inline void RiceviNotifica(int msg) { vicini_futuri += msg; } }; // Contenitore di caselle, che genera automaticamente le corrispondenze tra vicini. // Gestisce le regole "topologiche" class Griglia{ public: typedef std::vector<Casella> Container; typedef Container::iterator Iterator; private: int righe_; int colonne_; Container griglia; public: virtual ~Griglia(){} Griglia(const int& righe, const int& colonne) :righe_(righe), colonne_(colonne) { if (righe_ < 5) righe_=5; if (colonne_ < 5) righe_=5; griglia.reserve(righe_*colonne_); griglia.resize(righe_*colonne_); } inline Casella& operator[](const int n) { return griglia[n]; } inline void Cicla() { for (int i = 0; i < righe_*colonne_;++i) griglia[i].Ciclo(); } void Verifica(){ for (int i = 0; i < righe_*colonne_;++i) griglia[i].Verifica(); } inline void Imposta (const int& pos) { if ((pos >=0)&&(pos < griglia.size())) griglia[pos].Nasci(); } inline void Resetta (const int& pos) { if ((pos >=0)&&(pos < griglia.size())) griglia[pos].Muori(); } // Modificare questa routine per cambiare le regole topologiche di vicinanza inline void Genera(){ bool primo, ultimo; for (int indice=0; indice< righe_*colonne_;++indice){ primo = ( (indice%colonne_) == 0); ultimo = ( (indice%colonne_) == colonne_-1); if (indice > colonne_){ if (!primo) griglia[indice].Registra(griglia[indice-colonne_ - 1]); griglia[indice].Registra(griglia[indice-colonne_]); if (!ultimo) griglia[indice].Registra(griglia[indice-colonne_ + 1]); } if (!primo) griglia[indice].Registra(griglia[indice-1]); if (!ultimo) griglia[indice].Registra(griglia[indice+1]); if (indice < ((colonne_)*(righe_-1)) ){ if (!ultimo) griglia[indice].Registra(griglia[indice+colonne_+1]); griglia[indice].Registra(griglia[indice+colonne_]); if (!primo) griglia[indice].Registra(griglia[indice+colonne_-1]); } } } inline const int Righe() const { return righe_; } inline const int Colonne() const { return colonne_; } }; //Stampa a schermo la griglia. Gestione statica delle dimensioni. Per variare, utilizzare griglia.Righe() e Colonne() void Stampa( Griglia& g) { cout << "\n\n"; cout << "+--------------------+\n|"; for (int indice=0;indice < 400;++indice){ bool ultimo = ( (indice%20) == 19); g[indice].Leggi()?cout << "O":cout << " "; if (ultimo){ if (indice !=399) {cout << "|\n|";} else {cout << "|\n";} } } cout << "+--------------------+\n"; } int main () { Griglia griglia(20,20) ; griglia.Genera(); // Inizializza la griglia casualmente, con fattore di // riempimento un ottavo. // Gestione statica delle dimensioni. Per variare, utilizzare griglia.Righe() e Colonne() srand(time(0)); for (int i=0; i < 100;++i){ griglia.Imposta((rand()>>4) %400); } while (1){ Stampa(griglia); griglia.Cicla(); griglia.Verifica(); // Aspetta la pressione di enter cin.get(); } // Mai raggiunto return 0; }