"Bingo" in C++ - Benötige Hilfe/Ansatz



  • Guten Abend.

    brauche für meine Wochenübung in Informatik etwas Hilfe, bzw. einen konkreten Ansatz. Leider blicke ich bei der Aufgabe nicht so wirklich durch. Bin soweit schon recht fit in C++ (soweit wie wir es bis jetzt behandelt haben).

    Erstmal die Aufgabenstellung:

    Aufgabe 1: Klassen (3 Punkte)

    Bei dem Spiel Bingo besitzt jeder Spieler eine oder mehrere Spielkarten. Auf jeder Spielkarte stehen Zahlen, die in einer quadratischen Matrix angeordnet sind. Diese Zahlen stammen aus einem vorab festgelegten Zahlenbereich und unterscheiden sich von Karte zu Karte. Nach und nach werden zufällig Zahlen gezogen. Die Spieler überprüfen jeweils, ob die gezogene Zahl auf einer ihrer Karten vorkommt. Falls dies der Fall ist, streichen sie die Zahl durch. Derjenige Spie- ler, der zuerst auf einer seiner Spielkarten in einer Zeile oder Spalte alle Zahlen durchstreichen konnte, ruft laut Bingo und gewinnt das Spiel.

    Ergänzen Sie das nachfolgende Programm um die Definitionen der Klassen Bingokarte und Spieler. Objekte der Klasse Bingokarte sollen Bingo-Spielkarten repräsentieren. Sie be- stehen aus einem 4x4 großen Zahlenfeld. Wenn eine Zahl gezogen wird, soll mit Hilfe einer Methode ¨uberpr¨uft werden k¨onnen, ob diese Zahl in dem Zahlenfeld vorkommt. Falls ja, soll ” Treffer“ ausgegeben werden. Zusätzlich soll getestet werden, ob diese Zahl und alle zuvor getesteten Zahlen eine Reihe oder Spalte auf der Spielkarte bilden.

    Ein Spieler besitzt mehrere Spielkarten, die über die Methode neueKarte dem Spieler zugeordnet werden. Mit der Methode Bingo überprüft ein Spieler alle seine Spielkarten auf eine gezogene Zahl. Sobald von einer Spielkarte alle Zahlen einer Reihe oder Spalte gezogen wurden, soll neben ” Bingo“ folgendes ausgegeben werden:

    • die Nummer der entsprechenden Spielkarte des Spielers
    • die Angabe ob eine Reihe oder Spalte auf der Spielkarte zum Gewinn führt incl. Angabe des entsprechenden Index
    • die Gewinnzahlen der entsprechenden Reihe oder Spalte. Dabei muss Bingo den Wahrheitswert true zurückgeben. Andernfalls soll diese Methode false zurückgeben.

    Beachten Sie bei Ihrer Lösung der Aufgabe, dass Speicherplatz für dynamisch allokierte Objekte auch wieder freigegeben wird. Speichern Sie Ihre Lösung für diese Aufgabe in der Datei Aufgabe_08_1.cpp. Der vorgegebene Hauptprogramm darf nicht verändert werden! Kompilieren Sie Ihr Programm und führen Sie es anschließend aus. Kopieren Sie die Ergebnisse als Block-Kommentar an das Ende der Datei Aufgabe_08_1.cpp. (3 Punkte)

    Die vorgeschriebene "Aufgabe_08_1.cpp"

    #include <iostream>
    #include <stdlib.h>
    using namespace std;
    
    //***************************************** 
    // Hier bitte die Klassendefinitionen // Bingokarte und Spieler ergaenzen
    //*****************************************
    
    int main() {
    	unsigned int belegungA[4][4] = {
    			{ 1,	8,	14,	5 },
    			{ 16,	2,	9,	11 },
    			{ 7,	12,	3,	6 },
    			{ 17,	18, 4,	9 } };
    
    	unsigned int belegungB[4][4] = {
    			{ 10,	18,	8,	1 },
    			{ 3,	16,	2,	8 },
    			{ 15,	17,	7,	3 },
    			{ 11,	13,	5,	4 } };
    
    	Bingokarte *spielkarteA, *spielkarteB;
    	spielkarteA = new Bingokarte (belegungA);
    	spielkarteB = new Bingokarte (belegungB);
    
    	unsigned int maximaleSpielkartenanzahlProSpieler = 4;
    	Spieler hugo (maximaleSpielkartenanzahlProSpieler);
    	hugo.neueKarte (spielkarteA);
    	hugo.neueKarte (spielkarteB);
    
    	srand(15412);
    	unsigned int zufallszahl;
    	do {
    		zufallszahl = rand() * 20 / RAND_MAX;
    		cout << "Ziehe " << zufallszahl << endl;
    	} while (!hugo.Bingo(zufallszahl));
    
    	delete spielkarteA;
    	delete spielkarteB;
    
    	return 0;
    }
    

    Wir brauchen halt zwei Klassen. Einmal

    class Bingokarte {};
    

    und einmal

    class Spieler {};
    

    Wie kann ich das realisieren, dass sich das Programm die gezogenen Zahlen merkt und sie vergleicht, ob sie in einer Zeile oder Spalte stehen. Und das genau dann "Bingo" ausgegeben wird?

    Hatte bisher noch keine Probleme mit den Aufgaben, aber bei dieser versagt gerade alles 😞

    Ich hoffe ihr könnt mir ein paar Tipps und/oder Ansätze geben.

    LG



  • Durch die Art der Aufgabenstellung ist ja schon einiges vorgegeben.
    Die Deklaration Deiner beiden Klassen könntest Du ja schon hinschreiben - d.h. erstmal ohne Implementierung.

    class Spieler{
    public:
    // Hier Deine oeffentlichen member
    };
    
    class Spielkarte{
    public:
    // dto.
    };
    


  • Das weiß ich auch und habe ich auch schon gemacht 😃

    Nur weiter weiß ich nicht. Habe auch schon über Google und ähnliches gesucht, aber leider nichts, was mir auf Anhieb hilft.


  • Mod

    Eledhon schrieb:

    Das weiß ich auch und habe ich auch schon gemacht 😃

    Zeig doch mal!

    Nur weiter weiß ich nicht. Habe auch schon über Google und ähnliches gesucht, aber leider nichts, was mir auf Anhieb hilft.

    "Programmieren" bedeutet ja auch nicht "Code aus dem Internet zusammen kopieren". Falls du deine bisherigen Hausaufgaben auf diese Art und Weise gelöst hast, ist klar, dass du irgendwann in Schwierigkeiten kommen musstest.



  • Der Compiler hilft dir doch (mit Fehlern!) - du mußt jetzt noch die passenden Klassenfunktionen deklarieren (und definieren).

    Intern mußt du beim Spieler dir eine Liste der Karten merken (std::vector<Bingokarte> würde ich dafür empfehlen).
    Du mußt dann dir irgendwie markieren, ob eine Zahl gezogen worden ist (entweder alle Zahlen selbst in einer eigenen Liste merken und dann die Spielkarten daraufhin für die Reihen und Spalten überprüfen oder aber direkt in der Belegung beim Ziehen die Zahl mit z.B. 0 oder -1 o.ä. überschreiben und dann dementsprechend die Reihen und Spalten abprüfen.



  • Nur weiter weiß ich nicht. Habe auch schon über Google und ähnliches gesucht, aber leider nichts, was mir auf Anhieb hilft.

    "Programmieren" bedeutet ja auch nicht "Code aus dem Internet zusammen kopieren". Falls du deine bisherigen Hausaufgaben auf diese Art und Weise gelöst hast, ist klar, dass du irgendwann in Schwierigkeiten kommen musstest.

    Nein, mache die Aufgaben mit dem, was ich in der Vorlesung lerne und das, was im Script zu diesen steht. Nur manchmal brauch mal halt einen Ansatz, um auf die richtige Spur zu kommen. Dieses Problem habe ich gerade.

    Den main-Teil dürfen wir nicht verändern, den lasse ich jetzt mal weg (oben nachlesen). Hier meine Klassen usw:

    // Klassen
    class Bingokarte {
    private:
    public:
    	Bingokarte(unsigned int _belegung);
    
    };
    
    class Spieler {
    private:
    public:
    
    	Spieler(unsigned int&);
    	void neueKarte(Bingokarte*&);
    	bool Bingo(unsigned int _zufallszahl);
    };
    
    //  Funktionen
    	void neueKarte(Bingokarte*&) {
    
    	}
    	bool Bingo(unsigned int _zufallszahl) {
    
    	}
    

  • Mod

    Die main-Funktion oben ist nicht von dir, sondern von deinem Lehrer?

    😮

    Tut mir leid für dich. Du hast kein C++ gelernt, sondern einen Java-Kurs belegt, dessen Lehrer mal 5 Minuten geguckt hat, wie er seine Java-Sachen in C++ ausdrücken kann. Das ist wie der Versuch, allein mit einem Vokabelbuch eine andere Sprache zu sprechen.

    Tut mir leid, dass diese Antwort nicht wirklich auf deine Frage eingeht (später, wenn ich mehr Zeit habe, kann ich genauer gucken), aber das musste gesagt werden. In diesem Kurs wirst du nur Dinge lernen, die du dir später wieder mühsam abgewöhnen musst.



  • Ich studiere Physik mit Informatik bzw. "Einführung in die Programmierung" als Nebenfach im ersten Semester.

    Wir haben jetzt wochenlang "c" gelernt (fangen jetzt so langsam an C++ Strings zu lernen).

    Die Main ist vom Prof ja. Aber daran kann ich leider nichts ändern.

    Irgendwie muss ich mir die Klassen zusammenbasteln... und btw, wie gesagt, die Scripts / PowerPoint Folien zu dem Kapitel "Klassen" sind mehr als ungenügend.



  • Der Konstruktor von Bingokarte ist falsch. Da wird ein unsigned int[4][4] übergeben.
    Aus ästhetischen Gründen würde ich hier ein typedef spendieren.

    Und die Referenz in Spieler::neueKarte() würde ich mir auch sparen.

    using array4x4 = unsigned int[4][4];
    
    class Bingokarte {
    private:
    public:
      Bingokarte(const array4x4& arr);
    };
    
    class Spieler {
    private:
    public: 
        Spieler(unsigned int max);
        void neueKarte(Bingokarte* karte);
        bool Bingo(unsigned int zahl);
    };
    

    Um möglichst schnell Abstand zu der schrottigen main() zu bekommen, schlage ich vor, dass Bingokarte ein int[4][4] (nicht unsigned!) als Member erhält und wir im Konstruktor das array4x4 arr da hineinkopieren.

    Dann würde ich Bingokarte eine Funktion void Bingokarte::pruefe(int z) oder so spendieren, die alle Vorkommnisse von z im internen Array mit -1 überschreibt - ganz wie Th69 es vorgeschlagen hat.

    Klingt das plausibel?

    Kannst Du u.U. auch schon eine Funktion bool Bingokarte::pruefe_reihen() implementieren, die alle Reihen einer Bingokarte auf viermal -1 prüft?



  • Okay.

    Also wenn ich die Vorgehensweise richtig verstehe, soll das Programm folgendes tun:

    Internes Array anlegen, dort Positionen der gezogenen/durchgestrichenen Zahlen ablegen. Dann mit einer 'pruefe' Funktionen abfragen, ob die abgelegten Zahlen eine Reihe bzw. Spalte einer der beiden "Bingokarten-Arrays" bilden. Wenn ja, startet die Funktion Bingo (wie in der Aufgabenstellung beschrieben), wenn nein, dann ziehe die nächste Zahl, lege sie ab, prüfe usw.

    Ist das so richtig?



  • Eledhon schrieb:

    Internes Array anlegen, dort Positionen der gezogenen/durchgestrichenen Zahlen ablegen.

    Nein, die Zahlen aus dem übergebenen Array ablegen. (Z.23 und 24 aus main()).

    Eledhon schrieb:

    Dann mit einer 'pruefe' Funktionen abfragen, ob die abgelegten Zahlen eine Reihe bzw. Spalte einer der beiden "Bingokarten-Arrays" bilden.

    Nein. Eigentlich ist vielleicht auch der Name streiche() oder markiere() besser. Denn es sollen alle Vorkommnisse von z im internen Array mit -1 markiert werden (oder mit 0 oder sonstwas).

    Eledhon schrieb:

    Wenn ja, startet die Funktion Bingo (wie in der Aufgabenstellung beschrieben), wenn nein, dann ziehe die nächste Zahl, lege sie ab, prüfe usw.

    Nein. Spieler::Bingo() ist noch gar nicht im Fokus. Erstmal nur die Bingokarte - und die soll pruefen, ob irgendwo eine Reihe oder eine Spalte komplett markiert ist.

    class Bingokarte{
      bool pruefe_reihen() const;
      bool pruefe_spalten() const;
      ...
    public:
      bool bingo() const {
        return pruefe_reihen() || pruefe_spalten();
      }
      void markiere(int z);
      ....
    };
    

    Eledhon schrieb:

    Ist das so richtig?

    Bisher haben wir uns ziemlich missverstanden... 😞

    Ist vielleicht auch schon alles viel zu detailiert - sieh es nur als Vorschlag.

    PS: Kann sich jemand einen Reim auf Z. 34 im Hauptprogramm machen?


  • Mod

    Furble Wurble schrieb:

    PS: Kann sich jemand einen Reim auf Z. 34 im Hauptprogramm machen?

    Der Programmierer hat mal davon gehört, dass die übliche Modulo-Methode einen Bias habe und hat sich dann selber eine Lösung dafür überlegt. Diese hat er dann auf seinem Windowssystem erfolgreich getestet und nicht weiter darüber nachgedacht, ob das auch wirklich richtig ist. Die Qualität dieses Programmierkurses habe ich ja bereits angesprochen. Es ist zwar theoretisch alles irgendwie richtig, aber praktisch vollkommen falsch.



  • Tut mir ja Leid 😞

    Das Problem bei der ganzen Veranstaltung ist, dass wir "Neulinge" alle ins kalte Wasser geschmissen werden. Habe ich auch eigentlich kein Problem mit, hätte ich nicht noch zwei andere, vom Stellenwert her, wichtigere Fächer 😃

    Wir haben letzte Woche im Info-Praktikum erstmals mit Klassen gearbeitet. Da waren wir alle froh, dass sie eine vernünftige Header-Datei erstellen konnten, wo eine ganz normale Class mit Konstruktor und Funktion drin war.
    Jetzt, nur eine Vorlesung später (die gar nicht mehr über Klassen handelte) sollen wir sowas "mal ebend so" machen.
    Nun ja, könnt ihr ja genauso wenig was für wie ich 😃

    Aber habe dich jetzt (hoffentlich) verstanden. Ich werde das morgen nach Uni nochmal in Angriff nehmen. Frage auch morgen andere Studenten, wie die das Umgesetzt haben bzw. angefangen haben. Kann das ja mal hier bei Bedarf reinstellen.

    Jetzt schon mal danke an euch und nochmals sorry 😞


Anmelden zum Antworten