C++ Programm in Klaasen aufteilen



  • Ich bekomme es nicht hin, mein C++ Programm in .cpp und .h Dateien aufzuteilen.

    Als einzelne Datei funktioniert es einwandfrei jedoch brauche ich Hilfe bei den Referenzen.
    Wäre sehr erfreut über einige Antworten 🙄

    Hier das komplette Programm:

    #include <iostream>
    #include <vector>
    #include <algorithm> 
    #include <ctime>
    #include <string>
    
    using namespace std;
    
    class Karten
    {
    private:
    	char   m_karte;           //  'A'   ,'2', '3', '4', '5', '6', '7', '8', '9', 'Z', 'D', 'B', 'K'
    	int    m_wert,            //1 or 11 , 2  , 3  ,  4,   5 ,  6 ,  7 ,  8 ,  9,  10, 10,  10, 10
    		   m_symbol;          //0 Pik, 1 Kreuz, 2 Herz, 3 Karo
    	string m_nameS;           // Namen der Symbole
    	bool   m_vergeben;        //Überprüft, ob eine Karte schon gezogen wurde.
    
    	int zuordnen();
    
    public:
    	Karten(char, int);
    	Karten(const Karten&);
    
    	int getWert()			const;
    	int getSymbol()			const;
    	string getName()	    const;
    	bool getIstVergeben()   const;
    	char getKarten()        const;
    
    	void setVergeben(bool x);
    
    	void nameKarten();
    };
    
    int Karten::zuordnen()
    {
    	if (m_karte == 'A')        return 11;
    	else if (m_karte == 'Z' ||
    		     m_karte == 'B' ||
    		     m_karte == 'D' ||
    		     m_karte == 'K')   return 10;
    	else                       return (m_karte - '0');
    }
    
    Karten::Karten(char karteV, int symbol)
    {
    	m_karte = karteV;
    	m_wert = zuordnen();
    	m_symbol = symbol;
    	m_vergeben = false;
    }
    
    Karten::Karten(const Karten& karte)
    {
    	m_karte = karte.getKarten();
    	m_wert = karte.getWert();
    	m_symbol = karte.getSymbol();
    	m_nameS = karte.getName();
    	m_vergeben = karte.getIstVergeben();
    }
    
    int Karten::getWert() const
    {
    	return m_wert;
    }
    
    int Karten::getSymbol() const
    {
    	return m_symbol;
    }
    
    std::string Karten::getName() const
    {
    	return m_nameS;
    }
    
    bool Karten::getIstVergeben() const
    {
    	return m_vergeben;
    }
    
    char Karten::getKarten() const
    {
    	return m_karte;
    }
    
    void Karten::setVergeben(bool x)
    {
    	m_vergeben = x;
    }
    
    void Karten::nameKarten()
    {
    	switch (m_symbol)
    	{
    	case 0: m_nameS = "Pik";   break;
    	case 1: m_nameS = "Kreuz"; break;
    	case 2: m_nameS = "Herz";  break;
    	case 3: m_nameS = "Karo";
    	}
    	if      (m_karte == 'A') cout << "Ass";
    	else if (m_karte == 'B') cout << "Bube";
    	else if (m_karte == 'D') cout << "Dame";
    	else if (m_karte == 'K') cout << "Koenig";
    	else                     cout << m_wert;
    	cout << "  " << m_nameS << endl;
    }
    
    class Deck
    {
    private:
    	vector<Karten*> m_deck;
    
    public:
    	Deck();
    
    	void neuesDeck();
    	void mischen();
    	Karten geben();
    };
    
    Deck::Deck()
    {
    	//Initialize the deck: 
    	neuesDeck();
    	mischen();
    }
    
    void Deck::neuesDeck()
    {
    	for (int i = 1; i <= 13; ++i)
    	{
    		char c;
    		switch (i) {
    		case 1:  c = 'A'; break;
    		case 2:  c = '2'; break;
    		case 3:  c = '3'; break;
    		case 4:  c = '4'; break;
    		case 5:  c = '5'; break;
    		case 6:  c = '6'; break;
    		case 7:  c = '7'; break;
    		case 8:  c = '8'; break;
    		case 9:  c = '9'; break;
    		case 10:  c = 'Z'; break;
    		case 11:  c = 'B'; break;
    		case 12:  c = 'D'; break;
    		case 13:  c = 'K';
    		}
    		for (int n = 0; n <= 3; ++n)
    		{
    			m_deck.push_back(new Karten(c, n));
    		}
    	}
    }
    
    void Deck::mischen()
    {
    	random_shuffle(m_deck.begin(), m_deck.end()); // aus std
    }
    
    Karten Deck::geben()
    {
    	for (int i = 0; i < m_deck.size(); ++i)
    	{
    		if (!m_deck[i]->getIstVergeben())
    		{
    			m_deck[i]->setVergeben(1);
    			return (*m_deck[i]);
    		}
    	}
    }
    
    class Hand
    {
    
    private:
    	vector<Karten> m_hand;
    
    public:
    
    	void init(Karten, Karten);
    	void anzeigen();
    	void anzeigenDealer();
    	void neueKarte(Karten);
    
    	int getAnzKarten();
    	int getSummeWert();
    };
    
    void Hand::init(Karten karte1, Karten karte2)
    {
    	m_hand.push_back(karte1);
    	m_hand.push_back(karte2);
    }
    
    void Hand::anzeigen()
    {
    	for (vector<Karten>::iterator iter = m_hand.begin();
    		iter != m_hand.end(); (++iter))
    	{
    		iter->nameKarten();
    	}
    }
    
    void Hand::anzeigenDealer()
    {
    	m_hand[0].nameKarten();
    }
    
    void Hand::neueKarte(Karten karte)
    {
    	cout << "\nGezogen: ";
    	karte.nameKarten();
    
    	m_hand.push_back(karte);
    }
    
    int Hand::getSummeWert()
    {
    	int summe = 0;
    	for (vector<Karten>::iterator iter = m_hand.begin();
    		iter != m_hand.end(); (++iter))
    	{
    		summe += iter->getWert();
    	}
    	return summe;
    }
    
    int Hand::getAnzKarten()
    {
    	return m_hand.size();
    }
    
    class Spieler
    {
    protected:
    	Deck m_deck;
    	Hand m_hand;
    	bool m_imSpiel;
    	int stand;
    
    public:
    	Spieler(Deck deck);
    	void setzen();
    	void weitereKarte();
    	void ausgabe1();
    
    	int getStand() const;
    
    	bool verloren();
    	bool gewonnen();
    };
    
    Spieler::Spieler(Deck deck)
    {
    	m_imSpiel = 1;
    	m_deck = deck;
    	m_hand.init(deck.geben(), deck.geben());
    }
    
    void Spieler::setzen()
    {
    	m_imSpiel = 0;
    	stand = m_hand.getSummeWert();
    }
    
    void Spieler::weitereKarte()
    {
    	if (m_imSpiel) m_hand.neueKarte(m_deck.geben());
    	else cout << "Sie können keine weitere Karte ziehen!" << endl;
    }
    
    bool Spieler::verloren()
    {
    	if (m_hand.getSummeWert() > 21)
    	{
    		cout << "Ihre Hand ist größer als 21" << endl;
    		return true;
    	}
    	return false;
    }
    
    bool Spieler::gewonnen()
    {
    	return (m_hand.getSummeWert() == 21 && m_hand.getAnzKarten() == 2);
    }
    
    void Spieler::ausgabe1()
    {
    	cout << "Ihre Karten: \n";
    	m_hand.anzeigen();
    }
    
    int Spieler::getStand() const
    {
    	return stand;
    }
    
    class Dealer : public Spieler  //Der Dealer ist ein Spieler
    {
    public:
    	using Spieler::Spieler;
    
    	void ausgabe();
    	void spiel(Spieler);
    };
    
    void Dealer::ausgabe()
    {
    	cout << "Dealer's Karten: ";
    	m_hand.anzeigenDealer();
    	cout << endl;
    }
    
    void Dealer::spiel(Spieler spiel)
    {
    	while (m_hand.getSummeWert() <= 21)
    	{
    		cout << "Dealer's Karten: ";
    		m_hand.anzeigen();
    		cout << endl;
    		if (m_hand.getSummeWert() > spiel.getStand() && m_hand.getSummeWert() <= 21)
    		{
    			cout << "Der Dealer gewinnt, da sine Hand ueberlegen ist!" << endl;
    			return;
    		}
    		if (m_hand.getSummeWert() == spiel.getStand())
    		{
    			cout << "Ein Push! " << endl;
    			return;
    		}
    		weitereKarte();
    	}
    	if (m_hand.getSummeWert() > 21)
    	{
    		cout << "Dealer's Hand ist größer als 21." << endl;
    		cout << "Sie haben gewonnen!" << endl;
    		return;
    	}
    }
    
    void bedienung()
    {
    	cout << "Bedienung:" << endl;
    	cout << "1 fuer weitere Karte" << endl;
    	cout << "2 fuer halten" << endl;
    	cout << "\n\n";
    	cout << "Viel Spass!! \n\n" << endl;
    }
    
    int main()
    {
    	srand(time(0));
    
    	bedienung();
    
    	Deck deck;
    	Spieler benutzer(deck);
    	Dealer casino(deck);
    	char x;
    	bool bbreak = 0;
    
    	benutzer.ausgabe1();
    	casino.ausgabe();
    
    	if (benutzer.gewonnen())
    	{
    		cout << "Sie gewinnen! " << endl;
    	}
    	else if (casino.gewonnen())
    	{
    		cout << "Der Dealer gewinnt!" << endl;
    	}
    	else
    	{
    		while (!benutzer.verloren())
    		{
    			cout << "Was wollen Sie tun: ";
    			cin >> x;
    			if (x == '1')
    			{
    				benutzer.weitereKarte();
    			}
    			else if (x == '2')
    			{
    				benutzer.setzen();
    				casino.spiel(benutzer);
    				break;
    			}
    			benutzer.ausgabe1();
    			casino.ausgabe();
    		}
    	}
    
    	return 0;
    }
    

    Und hier meine Aufteilung (Versuch):

    Dealer.h :

    class Dealer : public Spieler  //Der Dealer ist ein Spieler
    {
    public:
    
    	void ausgabe();
    	void spiel(class Spieler& s);
    };
    

    Deck.h :

    class Deck
    {
    private:
    	std::vector<Karten*> m_deck;
    
    public:
    	Deck();
    
    	void neuesDeck();
    	void mischen();
    	Karten geben();
    };
    

    Hand.h :

    class Hand
    {
    
    private:
    
    	std::vector<Karten> m_hand;
    
    public:
    
    	void init(Karten, Karten);
    	void display();
    	void displayAsDealer();
    	void neueKarte(Karten);
    
    	int getNumOfCards();
    	int getSummeWert();
    };
    

    Karten.h :

    class Karten
    {
    private:
    	char m_karte;         //  'A'   ,'2', '3', '4', '5', '6', '7', '8', '9', 'Z', 'D', 'B', 'K'
    	int m_wert,         //1 or 11 , 2  , 3  ,  4,   5 ,  6 ,  7 ,  8 ,  9,  10, 10,  10, 10
    		m_symbol;             //0 Pik, 1 Kreuz, 2 Herz, 3 Karo
    	std::string m_nameS;
    	bool m_vergeben;        //Überprüft, ob eine Karte schon gezogen wurde.
    
    	int zuordnen();
    
    public:
    	Karten(char, int);
    	Karten(const Karten&);
    
    	int getWert()			const;
    	int getSymbol()			const;
    	std::string getName()	const;
    	bool getIstVergeben()   const;
    	char getKarten()        const;
    
    	void setVergeben(bool x);
    
    	void nameKarten();
    };
    

    Spieler.h :

    class Spieler
    {
    protected:
    	Deck m_deck;
    	Hand m_hand;
    	bool m_imSpiel;
    	int stand;
    
    public:
    	Spieler(Deck deck);
    	void setzen();
    	void weitereKarte();
    	void ausgabe1();
    
    	int getStand() const;
    
    	bool verloren();
    	bool gewonnen();
    };
    

    davor stehen jeweils immer:

    #pragma once
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <ctime>
    #include <string>

    So, jetzt die .cpp Dateien:

    Dealer.cpp :

    #include "Spieler.h"
    #include "Dealer.h"
    
    void Dealer::ausgabe()
    {
    	std::cout << "Dealer's Karten: ";
    	m_hand.displayAsDealer();
    	std::cout << std::endl;
    }
    
    void Dealer::spiel(class Spieler& spiel)
    {
    	while (m_hand.getSummeWert() <= 21)
    	{
    		std::cout << "Karten: ";
    		m_hand.display();
    		std::cout << std::endl;
    		if (m_hand.getSummeWert() > spiel.getStand() && m_hand.getSummeWert() <= 21)
    		{
    			std::cout << "Der Dealer gewinnt, da sine Hand ueberlegen ist!" << std::endl;
    			return;
    		}
    		if (m_hand.getSummeWert() == spiel.getStand())
    		{
    			std::cout << "Ein Push! " << std::endl;
    			return;
    		}
    		weitereKarte();
    	}
    	if (m_hand.getSummeWert() > 21)
    	{
    		std::cout << "Dealer's Hand ist größer als 21." << std::endl;
    		std::cout << "Sie haben gewonnen!" << std::endl;
    		return;
    	}
    }
    

    Deck.cpp :

    #include "Karten.h"
    #include "Deck.h"
    
    Deck::Deck()
    {
    	//Initialize the deck: 
    	neuesDeck();
    	mischen();
    }
    
    void Deck::neuesDeck()
    {
    	for (int i = 1; i <= 13; ++i)
    	{
    		char c;
    		switch (i) {
    		case 1:  c = 'A'; break;
    		case 2:  c = '2'; break;
    		case 3:  c = '3'; break;
    		case 4:  c = '4'; break;
    		case 5:  c = '5'; break;
    		case 6:  c = '6'; break;
    		case 7:  c = '7'; break;
    		case 8:  c = '8'; break;
    		case 9:  c = '9'; break;
    		case 10:  c = 'Z'; break;
    		case 11:  c = 'B'; break;
    		case 12:  c = 'D'; break;
    		case 13:  c = 'K';
    		}
    		for (int n = 0; n <= 3; ++n)
    		{
    			m_deck.push_back(new Karten(c, n));
    		}
    	}
    }
    
    void Deck::mischen()
    {
    	std::random_shuffle(m_deck.begin(), m_deck.end());
    }
    
    Karten Deck::geben()
    {
    	for (int i = 0; i < m_deck.size(); ++i)
    	{
    		if (!m_deck[i]->getIstVergeben())
    		{
    			m_deck[i]->setVergeben(1);
    			return (*m_deck[i]);
    		}
    	}
    }
    

    ...und so weiter

    Danke schonmal im voraus 😃



  • Du mußt in den einzelnen Headerdateien die entsprechenden Includes (oder Vorwärtsdeklarationen) einfügen, z.B.

    // Dealer.h
    #include "Spieler.h"
    
    class Dealer : public Spieler
    {
      // ...
    };
    

    oder

    // Deck.h
    #include "Karten.h"
    
    class Deck
    {
      // ...
    };
    

    Du solltest aber auch nur die Includes einfügen, die auch wirklich benötigt werden (also nicht generell die von dir erwähnten Standardheader).

    PS: Wenn du wirklich Anfänger bist, dann ist dein Code dafür sehr gut strukturiert und benannt (einzig bei "Karten" solltest du die Einzahl benutzen ;-)!

    Beim 2. Drüberschaun ist mir noch ein Anti-Pattern bei dir in Deck:neuesDeck() aufgefallen: Loop-switch sequence (for-case paradigm / Anti-Duff's Device)



  • Vielen Dank für die Antwort.

    Die Fehlerzahl hat sich somit von 64 auf 2 verringert 😃

    Nun bleibt noch ein Fehler in der main:

    int main()
    {
    	srand(time(0));
    
    	bedienung();
    
    	Deck deck;
    	Spieler du(deck);
    	Dealer casino(deck);  //<-- dieses "deck" ist rot unterkringelt
    	char x;
    	bool bbreak = 0;
    
    	du.ausgabe1();
    	casino.ausgabe();
    

    Die Beschreibung sagt: Keine Instanz des Konstruktors ""Dealer::Dealer"" stimmt nicht mit der Argumentenliste überein.

    Und: "Dealer::Dealer(Dealer &&)" Konvertierung von Argument1 von "Deck" in consr "Dealer&" nicht möglich.



  • Der Dealer hat bisher nur den Standardkonstruktor (diese werden nicht automatisch vererbt), d.h. du mußt diesen noch hinzufügen:

    Dealer::Dealer(Deck deck)
        : Spieler(deck)
    {
    }
    

    Und die Deklaration auch in der Headerdatei.

    Und du solltest den Parameter anpassen zu "Deck&" (oder "Deck*"), da du bisher jetzt immer eine Kopie des Decks weitergibst (auch in der Spieler-Klasse) - dann den Member m_deck auch zu einer Referenz (Zeiger) machen und per Initialisierungsliste initialisieren (so wie bei der Basisklasse).



  • Die änderungen mit dem Konstruktor habe ich angewendet.

    Jedoch nleibt die Fehlermeldung: " "Dealer::Dealer(Dealer &&)" Konvertierung von Argument1 von "Deck" in consr "Dealer&" nicht möglich."

    Wo genau muss ich die Referenzen machen?



  • Habe mal ne andere Frage. Das Programm startet jetzt zwar und ich sehe keine Probleme beim Spiel. Abeer ich kann es nur "ohne Debugger" strten, da nach einer Eingabe das Programm sofort schließt.
    Wenn ich es ohne Debugger starte läuft es so wie ich will.



  • Setze dann mal in der Zeile direkt nach der Eingabe einen Haltepunkt (breakpoint) und durchlaufe dann das Programm Zeile für Zeile (beim VS mit F10).



  • Dieser Thread wurde von Moderator/in Martin Richter aus dem Forum MFC (Visual C++) in das Forum C++ (alle ISO-Standards) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.


Anmelden zum Antworten