Schachfeld mit einer Verketteten Liste



  • hallo,
    ich muss ein Schachfeld programmieren, die Springfigur ist ("Pferdchen".
    Regeln: 2 Felder nach oben, rechts, links oder unten, dann 1 Feld senkrecht dazu.
    Ich bin noch am anfang des programms und schon stoße ich auf das erste Problem, irgendwie kann ich den String nicht initialisieren.
    Hier ist mein Programm:

    #include <iostream>
    #include <string>
    using namespace std;
    
    class Cschachfeld
    {
    private :
    	string spalten  ;
    	string reihen ;
    public:
    	Cschachfeld (string s  , string r) ;
    	~ Cschachfeld (){cout << "Destruktor: <Feldkoordinaten>." << endl;};
    };
    Cschachfeld :: Cschachfeld (string s  , string r) : spalten(s), reihen (r)
    {
    	s = {0,1,2,3,4,5,6,7};
    	r = {A,B,C,D.E,F,G,H};
    }
    

    Weisst jemand warum ich die beiden Feld so nicht initialiesieren kann?

    Für eure hilfe bedanke ich mich im voraus.
    Pava



  • Das ergibt von vorne bis hinten keinen Sinn. Was willst du da machen?



  • TyRoXx schrieb:

    Das ergibt von vorne bis hinten keinen Sinn. Was willst du da machen?

    oh ha, das hört sich gar nicht gut an.
    ich wollte erstmal die beiden felder initialisieren, und dann mit einer if oder for schleife weiter arbeiten.
    die aufgabe ist hier :
    Gehen Sie systematisch und schrittweise vor.
    o Erstellen Sie die Klasse „cSchachfeld“ mit 2 Attributen, die geeignet sind, um die
    Koordinaten des Schachfelds abzulegen.
    o Erstellen Sie einen Konstruktor, der die Koordinaten als Parameter entgegennimmt.
    o Erstellen Sie einen Destruktor, der die Ausgabe macht:
    „Destruktor: <Feldkoordinaten>“.
    o Bauen Sie ein Hauptprogramm, in welchem das Startobjekt der Klasse cSchachfeld
    mit den Startkoordinaten B 1 angelegt wird.
    o Bauen Sie eine Funktion springersprung(), die von Benutzer die Koordinaten einliest,
    an die der Springer ziehen soll.
    o Führen Sie in dieser Funktion eine Prüfung auf Korrektheit der Eingabe als
    zulässigen Springer-Sprung durch (erste Achse +/- 2, andere Achse +/- 1), beachten
    Sie dabei die Spielbrettgrenzen.
    o Die Funktion soll für einen korrekten Sprung ein neues cSchachfeld-Objekt mit den
    neuen Koordinaten generieren (new Operator) und an die verkettete Liste anhängen.
    o Rufen Sie im Hauptprogramm die Funktion springersprung() so oft auf, bis der
    Springer die gegenüberliegende Brettgrenze (Zielposition irgendwo in Reihe 😎
    erreicht hat,
    o Dann wird die Sprungkette ausgegeben (alle Koordinatenpaare inklusive Startposition
    und Zielposition), und die verkette Liste wird aufgelöst (delete Operator).



  • Das ist wohl so gemeint, dass die Klasse ein Feld auf dem Schachbrett darstellt. Jedes Feld soll seine Position kennen. Da sich die Felder durchnummerieren lassen und es zwei Achsen gibt, würde ich zwei Member-Variablen vom Typ unsigned int verwenden. Ungefähr so:

    class cSchachfeld
    {
    public:
    	unsigned int positionX;
    	unsigned int positionY;
    
    	//Konstruktor...
    
    	//Konstanten für die max. Koordinaten
    	enum
    	{
    		TotalWidth = 8,
    		TotalHeight = 8
    	};
    
    	//für mehr Komfort
    	bool fromChars(char letter, char number)
    	{
    		positionX = (toupper(letter) - 'A');
    		positionY = (number - '1');
    		return
    			positionX < (unsigned)TotalWidth &&
    			positionY < (unsigned)TotalHeight;
    	}
    };
    

    Benutzung:

    int main()
    {
    	cSchachfeld feld;
    	feld.fromChars('B', '1');
    }
    

    Für Sprünge könnte man eine Methode der Klasse cSchachfeld anlegen:

    bool jump(int deltaX, int deltaY)
    {
    	//negative Ergebnisse werden mit unsigned zu sehr hohen Werten und sind damit auch ungültig
    	positionX = unsigned(int(positionX) - deltaX);
    	//...
    	return
    		positionX < (unsigned)TotalWidth &&
    		//...
    		;
    }
    

    Das mit der Liste klingt sehr gewagt für einen Anfänger. Vielleicht tut's auch std::list :

    #include <list>
    #include <iostream>
    
    //...
    
    int main()
    {
    	std::list<cSchachfeld> turns;
    	cSchachfeld feld;
    	feld.fromChars('B', '1');
    	turns.push_back(feld);
    
    	//...
    
    	for (std::list<cSchachfeld>::iterator ii = turns.begin(); ii != turns.end(); ++ii)
    	{
    		std::cout << *ii << std::endl;
    	}
    }
    

    Die Ausgabe kann man so machen (das definiert den Operator << für cout und cSchachfeld ):

    std::ostream &operator << (std::ostream &os, const cSchachfeld &feld)
    {
    	return os << feld.positionX["ABCDEFGH"] << " " << feld.positionY["12345678"];
    }
    


  • erstmal vielen dank für die Antwort, aber ich habe diesen teil von deinem Code nicht verstanden:

    public:
    	unsigned int positionX;
    	unsigned int positionY;
    

    Ich glaube man sollte zwei atribute benutzen , das bedeutet für mich

    private :
    	unsigned int positionX;
    	unsigned int positionY;
    

    also private statt public, oder ist das falsch?



  • Du kannst die natürlich auch private machen und Methoden für den Zugriff anlegen. Bei einer so einfachen Struktur können öffentliche Attribute aber auch nicht schaden.



  • TyRoXx schrieb:

    Du kannst die natürlich auch private machen und Methoden für den Zugriff anlegen. Bei einer so einfachen Struktur können öffentliche Attribute aber auch nicht schaden.

    Ich würde die lieber public deklarieren aber der Professor will die als atribute haben. atribute heisst private oder?
    ich verstehe es auch nicht warum man für das erste praktikum so ein Programm auswählt.



  • pava schrieb:

    atribute heisst private oder?

    Bei Wikipedia steht nichts von private (da wird auch gar nicht auf Programmierung näher eingegangen). Also nennt man wohl alle Member-Variablen Attribute.



  • Danke schön jetzt bin ich einbischen schlauer geworden 😉
    Aber zwei Zeilen im Code verstehe ich immer noch nicht ganz (bin noch anfänger).

    positionX = (toupper(letter) - 'A');
    und das auch:
    std::ostream &operator << (std::ostream &os, const cSchachfeld &feld)

    also wenn ich usin name space std; mache dann brauche ich nicht mehr std: oder irre ich mich? übrigens ich verstehe nicht warum du os da benutzt hast.
    eine Frage hätte ich noch was ist toupper?



  • pava schrieb:

    also wenn ich usin name space std; mache dann brauche ich nicht mehr std: oder irre ich mich?

    Normalerweise gehört using namespace nicht in einen Header (wo normalerweise Klassendefinitionen stehen).

    pava schrieb:

    übrigens ich verstehe nicht warum du os da benutzt hast.
    eine Frage hätte ich noch was ist toupper?

    Zwei Fälle für Google.
    -> c++ operator overloading
    -> c++ toupper


Log in to reply