// // SameGame // eenvoudig programma dat het spel SameGame speelt // // Walter Kosters, Tim Cocx, 3.2.2014 // C++ // Compileren: g++ -Wall -Wextra -o samegame samegame.cc // #include #include #include using namespace std; const int MAX = 20; //hoogte < MAX en breedte < MAX const int KLEUREN = 5; //aantal kleuren; gebruik 1,2,3,...,KLEUREN const int checkdummy = 12345; //predeclaraties int haalgetal(int); // op dit speelveld wordt het spel gespeeld class bord { public: bord(); bord(int p, int q); void initattributen(); void initrandom(); void vulplek(int i, int j, int k); void print(); void doeactie(); bool einde(); void leesbordin(string bestand); void randombord(); void bordmenu(); private: void spelmenu(); void leeggebied(bool[][MAX]); void bepaalgebied(bool[ ][MAX], int r, int k, int kleur); int groottegebied(bool gebied[ ][MAX]); int hoegrootisgebied(int r, int k); int grootstegrootte(int & i, int & j); void herstellen(); void doezet(int r, int k, bool meteen); bool magzet(int r, int k); int telzetten(); void doezoveelstezet(int x); void randomzet(); int randomspel(); int montecarlospel(); int strategiespel(); int inhoud[MAX][MAX]; //het speelbord int kleuren[KLEUREN + 1]; //aantallen van iedere kleur int m; //aantal rijen int n; //aantal kolommen int punten; //behaalde punten //gebruik inhoud[1][1], inhoud[1][2], ..., inhoud[1][n] // inhoud[2][1], inhoud[2][2], ..., inhoud[2][n] // ... // inhoud[m][1], inhoud[m][2], ..., inhoud[m][n] }; //bord //default constructor bord::bord() { m = n = 15; initattributen(); }//bord::bord //overloaded constructor bord::bord(int p, int q) { m = p; n = q; initattributen(); }//bord::bord(.,.) //initialiseren van klasse attributen void bord::initattributen() { punten = 0; for (int i = 1; i <= KLEUREN; i++) kleuren[i] = 0; }// bord::initattributen //zet randombord op void bord::initrandom() { for (int i = 1; i <= m; i++) for (int j = 1; j <= n; j++) { inhoud[i][j] = 1 + rand() % KLEUREN; kleuren[inhoud[i][j]]++; }//for }//bord::initrandom //vult plek (i,j) in met kleur k void bord::vulplek(int i, int j, int k) { kleuren[k]++; inhoud[i][j] = k; }//bord::vulplek //print het bord op het beeldscherm void bord::print() { int temp; cout << endl << " "; for (int k = 1; k <= n; k++) cout << " " << k % 10; cout << endl << endl; for (int i = 1; i <= m; i++) { if (i < 10) cout << " " << i << ": "; else cout << " " << i << ": "; for (int j = 1; j <= n; j++) if (inhoud[i][j] == checkdummy) cout << " " << "X"; else cout << " " << inhoud[i][j]; cout << endl; }//for cout << endl << "Behaalde punten: " << punten << endl << "Grootste grootte: " << grootstegrootte(temp, temp) << endl << "Aantallen kleuren: "; for (int l = 1; l <= KLEUREN; l++) cout << l << ":" << kleuren[l] << " "; cout << endl << endl; }//bord::print // vraagt de speler ofwel om een zet, ofwel om een algoritme uit te voeren void bord::doeactie() { int r, k; // rij & kolom do { cout << "Actie" << endl << "----------------" << endl << "Zet doen: Geef rij..." << endl << "Spelmenuutje: 0" << endl; r = haalgetal(m); if (r == 0) { spelmenu(); return; }//if cout << "Geef kolom .. "; k = haalgetal(n); } while (!magzet(r, k)); doezet(r, k, false); }//bord::kieszet //true als geen zet meer mogelijk is bool bord::einde() { for (int i = 1; i <= m; i++) for (int j = 1; j <= n; j++) if (magzet(i, j)) return false; return true; }//bord::einde //laat mens een keuze maken voor de verschillende algoritmen void bord::spelmenu() { char menukeuze; cout << endl << "SpelMenuutje" << endl << "----------------" << endl << "Random Spelen: r" << endl << "Monte Carlo: m" << endl << "Strategie: s" << endl; cin >> menukeuze; switch (menukeuze) { case 'r': case 'R': randomspel(); break; case 'm': case 'M': montecarlospel(); break; case 's': case 'S': strategiespel(); break; } }//bord::spelmenu void bord::leeggebied(bool gebied[ ][MAX]){ for (int i = 1; i <= m; i++) for (int j = 1; j <= n; j++) gebied[i][j] = false; }//bord::leeggebied //bepaal recursief het gebied met kleur kleur waartoe (r,k) behoort //administreer dit in boolean array gebied void bord::bepaalgebied(bool gebied[ ][MAX], int r, int k, int kleur) { if (0 < r && r <= m && 0 < k && k <= n && inhoud[r][k] == kleur && !gebied[r][k]) { gebied[r][k] = true; bepaalgebied(gebied, r + 1, k, kleur); bepaalgebied(gebied, r - 1, k, kleur); bepaalgebied(gebied, r, k + 1, kleur); bepaalgebied(gebied, r, k - 1, kleur); }//if }//bord::bepaalgebied //hoe groot is het gebied? //administreer in inhoud int bord::groottegebied(bool gebied[ ][MAX]) { int i, j, grootte = 0; for (i = 1; i <= m; i++) for (j = 1; j <= n; j++) if (gebied[i][j]) { grootte++; inhoud[i][j] = checkdummy; }//if return grootte; }//bord::groottegebied //hoe groot is gebied waarin (r,k) ligt? int bord::hoegrootisgebied(int r, int k) { bool gebied[MAX][MAX]; int grootte = 0; if (r <= 0 || r > m || k <= 0 || k > n || inhoud[r][k] == 0) return 0; else if (magzet(r, k)) { leeggebied(gebied); bepaalgebied(gebied, r, k, inhoud[r][k]); for (int i = 1; i <= m; i++) for (int j = 1; j <= n; j++) if (gebied[i][j]) grootte++; return grootte; }//if else return 1; }//bord::hoegrootisgebied //wat is de grootte van het (een) grootste gebied? //(i,j) ligt daarin int bord::grootstegrootte(int & i, int & j) { int groot = 0; i = 0, j = 0; for (int p = 1; p <= m; p++) for (int q = 1; q <= n; q++) if (hoegrootisgebied(p, q) > groot) { groot = hoegrootisgebied(p, q); i = p; j = q; }//if return groot; }//bord::grootstegrootte //verwijder tussen-nullen, eerst in kolommen, en dan met //complete kolommen void bord::herstellen() { int i, j, k; for (j = 1; j <= n; j++) { k = m; for (i = m; i > 0; i--) if (inhoud[i][j] != 0) { inhoud[k][j] = inhoud[i][j]; k--; }//if for (; k > 0; k--) inhoud[k][j] = 0; }//for k = 1; for (j = 1; j <= n; j++) { if (inhoud[m][j] != 0) { for (i = 1; i <= m; i++) inhoud[i][k] = inhoud[i][j]; k++; }//if }//for for (; k <= n; k++) for (i = 1; i <= m; i++) inhoud[i][k] = 0; }//bord::herstellen //doe een zet op (r,k); check eerst of het mag. meteen bepaald of //er om bevestiging gevraagd moet worden void bord::doezet(int r, int k, bool meteen) { bord hulpbord = *this; char jaofnee='n'; bool gebied[MAX][MAX]; int grootte = 0; if (magzet(r, k)) { leeggebied(gebied); bepaalgebied(gebied, r, k, inhoud[r][k]); if (!meteen){ grootte = hulpbord.groottegebied(gebied); hulpbord.punten += (grootte - 2)*(grootte - 2); hulpbord.print(); cout << "Doen? (j/n) .. "; cin >> jaofnee; if (jaofnee == 'j' || jaofnee == 'J') meteen = true; } if (meteen){ grootte=0; for (int i = 1; i <= m; i++) for (int j = 1; j <= n; j++) if (gebied[i][j]) { grootte++; kleuren[inhoud[i][j]]--; inhoud[i][j] = 0; }//if punten += (grootte - 2)*(grootte - 2); herstellen(); }//if }//if }//bord::doezet //mag je op (r,k) zetten? bool bord::magzet(int r, int k) { return ( 0 < r && r <= m && 0 < k && k <= n && inhoud[r][k] != 0 && ((r > 1 && inhoud[r][k] == inhoud[r - 1][k]) || (r < m && inhoud[r][k] == inhoud[r + 1][k]) || (k > 1 && inhoud[r][k] == inhoud[r][k - 1]) || (k < n && inhoud[r][k] == inhoud[r][k + 1]))); }//bord::magzet //tel het aantal mogelijke zetten int bord::telzetten() { int i, j, teller = 0; for (i = 1; i <= m; i++) for (j = 1; j <= n; j++) if (magzet(i, j)) teller++; return teller; }//bord::telzetten // doe getelde zet k na het tellen van het aantal zetten void bord::doezoveelstezet(int k) { int i, j, teller; teller = 0; for (i = 1; i <= m; i++) for (j = 1; j <= n; j++) if (magzet(i, j)) { if (teller == k) { doezet(i, j, true); return; }//if teller++; }//if }//bord::doezoveelstezet // doe een random zet void bord::randomzet() { int dezet, aantalzetten; aantalzetten = telzetten(); dezet = rand() % aantalzetten; doezoveelstezet(dezet); }//bord::randomzet // speel het volledige spel met random zetten int bord::randomspel() { while (!einde()) { randomzet(); print(); }//while return punten; }//bord::randomspel // speel het volledige spel met een monte carlo strategie int bord::montecarlospel() { //TODO hier je eigen werk! return punten; }//bord::montecarlospel // speel het volledige spel met een eigen strategie int bord::strategiespel() { //hier je eigen werk! return punten; }//bord::strategiespel //pak getal van toetsenbord, maximaal maximaal int haalgetal(int maximaal) { int getal = 0; char kar = cin.get(); while (kar == '\n') kar = cin.get(); while (kar != '\n') { if ('0' <= kar && kar <= '9') { getal = 10 * getal + kar - '0'; if (getal > maximaal) getal = getal / 10; }//if kar = cin.get(); }//while return getal; }//haalgetal // start met een random bord void bord::randombord() { m = n = 5; initrandom(); }//bord::randombord // start met een bord dat ingelezen wordt uit een file void bord::leesbordin(string bestand) { ifstream invoer(bestand.c_str(), ios::in); if (!invoer) { cout << "File bestaat niet!" << endl; randombord(); return; }//if int inv; invoer >> m; invoer >> n; cout << "hoogte: " << m << ", breedte:" << n << endl; for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { invoer >> inv; vulplek(i, j, inv); }//for }//for invoer.close(); }//bord::leesbordin //laat mens kiezen uit random of bestaand bord void bord::bordmenu() { char menukeuze; string bestandkeuze; cout << endl << "BordMenuutje" << endl << "----------------" << endl << "Random Bord: r" << endl << "Bestaand bord: b" << endl; cin >> menukeuze; switch (menukeuze) { case 'r': case 'R': default: randombord(); break; case 'b': case 'B': cout << endl << "Welk bestand wil je?" << endl << "----------------" << endl; cin >> bestandkeuze; leesbordin(bestandkeuze); break; }//switch }//bord::bordmenu int main() { srand(9358); // initialiseer randomgenerator bord b; b.bordmenu(); while (!b.einde()) { b.print(); b.doeactie(); }//while cout << endl << "Eindstand:" << endl; b.print(); return 0; }//main