#include "maedn.h" using namespace std; // für iostream /////////////////////////////////////////////////////////////////////////////// void Initialisierung(MAEDN & m) { // // Init. der Teil-Datenstruktur Spielfeld, einlesen der Spielernamen etc. // // statt Einlesen, bisher nur Default-Werte // /////////////////////////////////////////////////////////////////////////////// // Werte richtig initialisieren int i,j; for(i=0;i die mit Wurf ziehen kann // /////////////////////////////////////////////////////////////////////////////// // ausnahmsweise Abweichung von der Standardumsetzung! // das Ergebnis des Tests wird mit return zurückgegeben // sonst müsste man für das Ergebnis noch einen formalen Parameter haben // ebenso in der aufrufenden Funktion, die Abfrage in der // if-Anweisung sähe dann so aus: // if (EinzelzugMoeglich(m,nr,figur,wert,erg),erg) // also zunächst der Aufruf und durch Verwendung des Komma-Operators // ist der Wahrheitswert der Bedingung der Inhalt der Variablen erg // Dieses Vorgehen bietet sich an, wenn das Ergebnis ausschließlich direkt // verwendet wird und nie einer Variablen zugewiesen werden soll. // Man kann dies auch als "anonyme" Ausgangsvariable (ohne Namen) betrachten // // Einzelzug mit der bestimmten Figur möglich, wenn // - Figur draußen // - das Feld "wert" weiter existiert // - und nicht durch eine eigene Figur besetzt ist // Es fehlt noch (falls gewünscht) Überprüfung, dass im Zielbereich keine // eigenen Figuren übersprungen werden if (m.spieler[nr].pos[figur]>=0) { if (m.spieler[nr].pos[figur]+wert noch frei, false -> schon besetzt } } else { return false; // Zug schießt über das Ziel hinaus } } else { return false; // Figur ist noch im Startbereich } } /////////////////////////////////////////////////////////////////////////////// bool SpielzugMoeglich(const MAEDN & m, const int nr, const int wert) { // // überprüft, ob Spieler mit Wurf eine Figur setzen kann // /////////////////////////////////////////////////////////////////////////////// if (EinzelzugMoeglich(m,nr,0,wert)) { return true; } else if (EinzelzugMoeglich(m,nr,1,wert)) { return true; } else if (EinzelzugMoeglich(m,nr,2,wert)) { return true; } else if (EinzelzugMoeglich(m,nr,3,wert)) { return true; } else { return false; } // dies ist die ausführliche Variante von // return ( EinzelzugMoeglich(m,nr,0,wert) || EinzelzugMoeglich(m,nr,1,wert) // || EinzelzugMoeglich(m,nr,2,wert) || EinzelzugMoeglich(m,nr,3,wert) ); } /////////////////////////////////////////////////////////////////////////////// void SchlageFigur(MAEDN & m, const int index) { // // Schlägt die Figur auf dem Feld , das Feld darf nicht leer sein // /////////////////////////////////////////////////////////////////////////////// int gegner,i; gegner=m.feld.besetzt[index]; cout << "Die Figur von " << m.spieler[gegner].name << " fliegt raus!" << endl; m.feld.start[gegner]++; m.spieler[gegner].aufFeld--; for(i=0;i<4;i++){ // vielleicht nicht so schön, dass man suchen muss, // welche der gegenerischen Figuren rausflog. // Evtl. kann man das noch in die Figuren codieren, // ist aber etwas aufwendig und an einigen Stellen zu ändern // => wir lernen an diesem Beispiel: Konstruktion einer // geeigneten Datenstruktur ist schwierig. Man hat selten zu // Beginn gleich alles mögliche im Sinn. // Spätere Änderungen sind immer aufwendig, // eine detaillierte Planung zahlt sich aus if (((m.spieler[gegner].pos[i]+10*gegner)%MAX_Felder) == index) { m.spieler[gegner].pos[i]=-1; break; // es kann nur eine geben ... } } } /////////////////////////////////////////////////////////////////////////////// void MacheZug(MAEDN & m, const int nr, const int figur, const int wert) { // // Führt den Zug für Spieler mit und Wurf aus // // darf nur aufgerufen werden, wenn der Spielzug möglich ist! // /////////////////////////////////////////////////////////////////////////////// // Es sind mehrere Fälle zu unterscheiden: // Lag die alte Position auf der Rundstrecke oder im Ziel // Liegt die neue Position auf der Rundstrecke oder im Ziel if (m.spieler[nr].pos[figur]+wert überhaupt einen Zug machen kann // // Einfacher automatischer Spieler: // // - wenn Figur auf Startposition, setze diese weg, wenn möglich // // - sonst wähle erste Figur (nach interner Zählung), die möglich ist // /////////////////////////////////////////////////////////////////////////////// int figur; figur=0; if (m.feld.besetzt[10*nr]==nr && m.feld.besetzt[10*nr+wert]!=nr) { // welche der 4 Figuren steht denn auf der Startposition? while (m.spieler[nr].pos[figur]!=0) { figur++; } } else { // suche erste mögliche Figur while (!(EinzelzugMoeglich(m,nr,figur,wert))) { figur++; } } // und nun noch den Zug ausführen ... cout << m.spieler[nr].name << " sagt: Ich setze Figur " << figur << endl; MacheZug(m,nr,figur,wert); } /////////////////////////////////////////////////////////////////////////////// void Spielzug1bis5(MAEDN & m, const int nr, const int wert) { // // Führt den Zug für Spieler aus, der eine gewürfelt hat // // (auch, wenn eine 6 gewürfelt hat und keine Figur raussetzen konnte) // /////////////////////////////////////////////////////////////////////////////// int i, figur; if (SpielzugMoeglich(m,nr,wert)) { cout << "Du hast eine " << wert << " gewuerfelt." << endl; if (m.spieler[nr].spieltmit!=1) { // dann ist es ein Computerspieler Computerzug(m,nr,wert); } else { // Hier müss(t)en nun alle Sonderregeln abgefangen werden, wie z.B. // Figur auf Startfeld muss weggezogen werden, // wenn noch weitere Figuren im Startbereich sind und der Zug möglich ist // ggf. Rauswerfpflicht? // kein Überspringen der eigenen Figuren im Zielbereich // (wobei das eher in EinzelzugMoeglich gehört) do { cout << "Welche Figur willst Du ziehen?" << endl; for(i=0;i<4;i++) { if (EinzelzugMoeglich(m,nr,i,wert)) { cout << "Figur " << i << " steht von Deiner Startposition " << "aus auf Feld " << m.spieler[nr].pos[i] << endl; } } cout << "Ich nehme Figur (eine der moeglichen Nummern auswaehlen) "; cin >> figur; // statt der Variablen figur könnte man auch i nehmen, // aber Lesbarkeit geht vor (vermeintlicher) Speichereffizienz // Aufgabe: was passiert, wenn der Spieler einen Wert <0 || >3 angibt? // Fangen Sie solche Eingaben noch ab! } while (!(EinzelzugMoeglich(m,nr,figur,wert))); // Wiederholung, // bis er endlich eine der möglichen Figuren gewählt hat // // und nun müssen wir den Zug noch ausführen ... MacheZug(m,nr,figur,wert); } } else { // gehört zu if (SpielzugMoeglich(m,nr,wert)) cout << "Schade, kein Zug mit einer " << wert << " moeglich." << endl; } } /////////////////////////////////////////////////////////////////////////////// void Spielzug6(MAEDN & m, const int nr) { // // Führt den Zug für Spieler aus, der eine 6 gewürfelt hat // /////////////////////////////////////////////////////////////////////////////// int i; // Zwangszug bei 6: Figur raussetzen, falls möglich if (m.feld.start[nr]>0 && m.feld.besetzt[10*nr]!=nr) { // noch Figuren am Start und Startfeld nicht durch eigene Figur besetzt cout << "Du hast eine 6 gewuerfelt! " << "Glueckwunsch! Neue Figur ist draussen!" << endl; if (m.feld.besetzt[10*nr]!=-1) { SchlageFigur(m,10*nr); } // else { ... } // Der eigene Zug ist unabhängig davon auszuführen m.feld.start[nr]--; m.spieler[nr].aufFeld++; // erste Figur finden, die noch draußen ist, auch das geht bestimmt schöner i=0; while (m.spieler[nr].pos[i]!=-1) { // mind. eine IST noch draußen i++; } m.feld.besetzt[10*nr]=nr; m.spieler[nr].pos[i]=0; } else { // alle anderen Sonderfälle wie bei 1 bis 5 Spielzug1bis5(m,nr,6); // etwas gemogelt :) - ist aber korrekt und kurz // sonstige Sonderfälle werden in Spielzug1bis5 behandelt } } /////////////////////////////////////////////////////////////////////////////// void GesamtzugSpieler(MAEDN & m, const int nr) { // // Gesamtzug für Spieler inkl. Wiederholungen nach 6 bzw. 3* am Anfang // /////////////////////////////////////////////////////////////////////////////// int count, wert; cout << "Spieler " << m.spieler[nr].name << " (Figuren-Nummer " << nr+1 << ") ist dran" << endl; if (m.spieler[nr].aufFeld==0) { // die Abfrage ist nicht korrekt // wenn keine Figur auf dem Feld ist, kann trotzdem noch ein Zug mit // einer Figur innerhalb des Zielbereichs möglich sein count=0; do { count++; GetWurf(wert); cout << count << "-ter Wurf: eine " << wert << " ..." << endl; } while (!(count==3 || wert==6)); if (wert==6) { do { Spielzug6(m,nr); SpielfeldAnzeigen(m.feld); GetWurf(wert); } while (!(wert!=6)); // ok, hier würde man zu wert==6 vereinfachen :) Spielzug1bis5(m,nr,wert); SpielfeldAnzeigen(m.feld); } } else { GetWurf(wert); while (wert==6) { Spielzug6(m,nr); SpielfeldAnzeigen(m.feld); GetWurf(wert); } Spielzug1bis5(m,nr,wert); SpielfeldAnzeigen(m.feld); } } /////////////////////////////////////////////////////////////////////////////// void MeinMAEDN(void) { // das "Hauptprogramm" für das MÄDN-Spiel // /////////////////////////////////////////////////////////////////////////////// MAEDN m; int nr; Initialisierung(m); do { Auswuerfeln(MAX_Spieler,nr); } while (!(m.spieler[nr].spieltmit!=0)); // kleine Mogelpackung, // das Auswürfeln wird wiederholt, falls ein Spieler ermittelt wird, // der garnicht mitmacht. Die do-while-Schleife wieder entfernen, // nachdem die Auswuerfeln-Routine angepasst wurde! cout << "Der Spieler " << m.spieler[nr].name << " faengt an!" << endl; // SpielfeldAnzeigen(m.feld); nr--; // kleiner Trick do { // damit hier einheitlich der nächste Spieler bestimmt werden kann nr=(nr+1)%MAX_Spieler; if (m.spieler[nr].spieltmit>0) { // Mensch oder Computer GesamtzugSpieler(m,nr); } } while (!(m.spieler[nr].imZiel==4)); cout << "Glueckwunsch! " << m.spieler[nr].name << " hat gewonnen!" << endl; }