Turmbau zu Babel
-
Hallo liebes Forum.
Meine Aufgabe ist es, die Türme von Babel grafisch mit C++ zu programmieren.
Ich schaffe es, dass das Programm weiß, wie es ziehen muss.
Aber ich scheitere an der grafischen Umsetzung.
Hier mein bisheriger Code:#include <iostream> #include <fstream> using namespace std; const int AnzahlderScheiben = 3; /* Eigentlich wollte Ich mit cin cout das Programm für n Scheiben schreiben, aber es klappt nicht, mein Ansatz: int AnzahlderScheiben cout << "Geben Sie die Anzahl der Scheiben ein:"; cin >> AnzahlderScheiben; */ int Stab_1[AnzahlderScheiben]; int Stab_2[AnzahlderScheiben]; int Stab_3[AnzahlderScheiben]; int* Stab_Array[3] = {Stab_1, Stab_2, Stab_3}; int main(int argc, char* argv[]); void Babel(int Scheiben, int von, int nach, int Hilf); void bewege(int von, int nach); void zeichne(); int main(int argc, char* argv[]) { for (int i = 0; i < AnzahlderScheiben; i++) { Stab_Array[0][i] = AnzahlderScheiben-i; Stab_Array[1][i] = 0; Stab_Array[2][i] = 0; } zeichne(); Babel(AnzahlderScheiben, 0, 1, 2); getchar(); return 0; } void babel(int Scheiben, int von, int nach, int Hilf) { if (Scheiben == 0) return; babel(Scheiben-1,von,Hilf,nach); zeichne(); babel(Scheiben-1,Hilf,nach,von); zeichne(); } void bewege(int von, int nach) { //Hier weiß ich noch nicht was ich schreiben soll } void zeichne() { for (int i = 0; i < AnzahlderScheiben; i++) { for (int j = 0; j < 3; j++) { int Scheiben = Stab_Array[j][AnzahlderScheiben-1-i]; for (int k = AnzahlderScheiben-1; k >= 0; k--) if (k >= Scheiben) cout << " "; else cout << "<"; cout << "|"; for (int k = 0; k < AnzahlderScheiben; k++) if (k >= Scheiben) cout << " "; else cout << ">"; cout << " "; } cout << "\n"; } for (int i = 0; i < AnzahlderScheiben*3*2+(3-1)*2+3; i++) cout << "-"; cout << "\n\n"; }
Vielleicht könnt ihr mir weiterhelfen.
Vielen Dank schonmal
-
Das heißt "Türme von Hanoi".
-
Irgendwie stehen Frage und Code in Konkurrenz...
Ich schaffe es, dass das Programm weiß, wie es ziehen muss.
Aber ich scheitere an der grafischen Umsetzung.void bewege(int von, int nach) { //Hier weiß ich noch nicht was ich schreiben soll } void zeichne() { for (int i = 0; i < AnzahlderScheiben; i++) { for (int j = 0; j < 3; j++) { int Scheiben = Stab_Array[j][AnzahlderScheiben-1-i]; for (int k = AnzahlderScheiben-1; k >= 0; k--) if (k >= Scheiben) cout << " "; else cout << "<"; cout << "|"; for (int k = 0; k < AnzahlderScheiben; k++) if (k >= Scheiben) cout << " "; else cout << ">"; cout << " "; } cout << "\n"; } for (int i = 0; i < AnzahlderScheiben*3*2+(3-1)*2+3; i++) cout << "-"; cout << "\n\n"; }
-
besserwisser schrieb:
Das heißt "Türme von Hanoi".
Turmbau zu Babel macht die Sache aber viel einfacher:
void baue_turm(unsigned &anzahl_stockwerke) { baue_turm(++anzahl_stockwerke); } int main() { unsigned anzahl_stockwerke=0; baue_turm(anzahl_stockwerke); }
Das endet dann auch ähnlich fatal wie Mythos.
-
Hatten wir schon: http://www.c-plusplus.net/forum/277823?highlight=t�rme+hanoi
SeppJ schrieb:
...
Ich war neugierig wie lange das Programm durchhält. Ganze 4793 Stockwerke.
Allerdings ist der Compiler clever:
warning C4717: 'baue_turm' : recursive on all control paths, function will cause runtime stack overflow
-
JaykopX schrieb:
Hatten wir schon: http://www.c-plusplus.net/forum/277823?highlight=t�rme+hanoi
SeppJ schrieb:
...
Ich war neugierig wie lange das Programm durchhält. Ganze 4793 Stockwerke.
Allerdings ist der Compiler clever:
warning C4717: 'baue_turm' : recursive on all control paths, function will cause runtime stack overflow
Bei mir hat es SEHR lange durchgehalten. Hat auch quasi das gesamte System lahmgelegt, bevor irgendwann das erlösende "Killed" kam. Festplatte war auch voll am abrödeln, weil alles ausgelagert wurde.
Habe mal geguckt, meine Stackgröße ist "unlimited". Bin mir nun nicht mehr so sicher, ob dies eine gute Idee ist
.
-
Das Problem ist, dass mir das Programm jedes mal den gleichen Turm ausspuckt.
Es soll mir halt grafisch zeigen, wie die einzelnen Schritte sind um den einen Stapel auf den anderen zu verschieben , wenn eben nur kleinere auf größeren Scheiben liegen dürfen.
Könnt ihr mir da helfen, inwieweit void bewege aussehen muss und ob die restlichen Funktionen korrekt sind?
Vielen Dank
-
Hilbert schrieb:
Das Problem ist, dass mir das Programm jedes mal den gleichen Turm ausspuckt.
Was nichtg groß verwunderlich ist, da
bewege
gar nichts macht.Hilbert schrieb:
Könnt ihr mir da helfen, inwieweit void bewege aussehen muss und ob die restlichen Funktionen korrekt sind?
Genau das ist doch deine Aufgabe. Aber ich gebe dir mal einen Tipp:
Wie würdest du es angehen, einen Turm der Höhe 1 von Säule A auf Säule C zu verschieben? Ich nehme mal an, du kannst dafür eine Lösung finden. Nennen wir diese Lösung mal
bewege(1,A,C)
.Wie würdest du es angehen, einen Turm der Größe 2 von Säule A auf Säule C zu verschieben? Auch dafür kannst du sicherlich eine Lösung angeben. Kannst du diese Lösung durch Kombination verschiedener
bewege(1, start, ziel)
angeben? Nennen wir die Lösung malbewege(2,A,C)
.Wie würdest du es angehen, einen Turm der Größe 3 von Säule A auf Säule C zu verschieben? So langsam wird's schon schwierig. Kannst du diese Lösung durch Kombination verschiedener
bewege(1, start, ziel)
undbewege(2, start, ziel)
angeben? Nennen wir die Lösung malbewege(3,A,C)
.Wie würdest du es angehen, einen Turm der Größe N von Säule A auf Säule C zu verschieben. Ein genauer Lösungsweg ist sehr schwer anzugeben, aber wenn du die vorherigen Fragen beantwortet hast, kannst du die Lösung vielleicht als Kombination verschiedener
bewege(1, start, ziel)
undbewege(N-1, start, ziel)
angeben.Und das setzt du jetzt als Computerprogramm um.
edit: Was mich an deiner Zeichenroutine stört: Die Dicke der Scheiben wird gar nicht beachtet. Wenn ich vom Turm oben eine Scheibe abhebe, dann werden die darunterliegenden Scheiben automatisch dünner. Vielleicht solltest du dir neben der Anzahl der Scheiben auch noch merken, wie dick jede Scheibe ist.
-
Okay danke erstmal.
Ja das ist eine schwierigere Aufgabe für Informatik.
Blick da leider nicht so durch, Informatik muss ich belegen, habe aber keine großen Kenntnisse davon.Den Algorithmus habe ich glaube schon ausgetüftelt:
Um den ganzen Turm von A nach C zu bekommen muss das Programm ja alle Scheiben außer der Untersten nach B verschieben.
Also n-1 Scheiben von A nach B.
Umd das zu bewerkstelligen muss man ja von diesen n-1 wieder n-1 nach C bekommen also n-2 erstmal von A nach C usw.Ich habe schon ein Programm geschrieben, welches mir alle Züge aufschreibt die es machen müsste.
Das Problem der Aufgabe ist, es zeichnerisch mit Hilfe der Arrays hinzubekommen.Also hab ich doch folgendes:
void Babel(int Scheiben, int von, int nach, int Hilf); if (Scheiben == 0) return; babel(Scheiben-1,von,Hilf,nach); babel(Scheiben-1,Hilf,nach,von);
Jetzt muss ichs ja auch ans Bewegen bringen:
Das kann ich ja dann nur mit den Arrays machen oder nicht?Im Fall AnzahlderScheiben = 1, wäre es A->C.
Im Fall AnzahlderScheiben = 2, wäre es A->B, A->C, B->C
Im Fall AnzahlderScheiben = 3, wäre es A->C, A->B, C->B, A->C, B->A,B->C,A->C.
Also muss ich erstmals die Breite oder den Radius meiner Scheibe irgendwie behalten.
Ich muss wissen welches Feld Frei ist und wie er ziehen muss.
Ich bin leicht überfordert..
-
Hilbert schrieb:
Okay danke erstmal.
Ja das ist eine schwierigere Aufgabe für Informatik.
Blick da leider nicht so durch, Informatik muss ich belegen, habe aber keine großen Kenntnisse davon.Dann machen wir doch auch mal Informatik!
Disclaimer: Um besser folgen zu können, benutze ausgiebig Wikipedia, www.cplusplus.com und Google!
Fangen wir mal an, bei vernünftigen Datenstrukturen, dann fällt der Rest viel leichter:
Ich sehe bei dem Problem zwei Arten von Objekten unserer Vorstellungswelt: Die Scheiben und die Säulen auf denen sie liegen. Ein abstraktes Objekt unserer Vorstellungswelt nennt man in C++ eine Klasse und eine Klasse ist eine Ansammlung von Eigenschaften und Fähigkeiten eines solchen Objekts.Eine Scheibe hat nur ihre Dicke als Eigenschaft, also schreiben wir:
class Scheibe { private: uint dicke; public: Scheibe(uint dicke): dicke(dicke){} };
Eine Säule ist eine Ansammlung von Scheiben. Man kann oben eine Scheibe drauflegen und man kann die oberste Scheibe wieder runternehmen. Die Klasse für die Säule hat also als Eigenschaft die Scheiben die auf ihr liegen und die Fähigkeit, oben was drauf und wieder runterzunehmen. Das wäre recht einfach selbst zu schreiben, aber sowas gibt es auch schon. Das was ich beschrieben habe nennt man in der Informatik einen Stack, zu deutsch Stapel. Eine Säule ist nichts anderes als ein Stapel von Scheiben:
#include<stack> typedef std::stack<Scheibe> Saeule;
Soweit die Datenstrukturen.
Jetzt können wir uns Gedanken machen, was man mit den Datenstrukturen machen kann. Die Mönche in Hanoi machen nur eines: Sie verschieben Scheiben von einer Säule zur anderen. Dazu schreiben wir eine Funktion:
void verschiebe(Saeule &von, Sauele &nach) { nach.push(von.top()); von.pop(); }
Ist nicht 100% realistisch, weil für einen kurzen Augenblick die Scheibe gleichzeitig auf beiden Säulen ist, aber wir wollen mal nicht so kritisch sein. Nach Abschluss der Funktion ist die Scheibe jedenfalls verschoben.
Die Mönche haben auch eine Idee wie sie vorgehen müssen, um N Scheiben zu verschieben. Du hast ja selber darüber nachgedacht. Der Obermönch hat folgenden Algorithmus aufgeschrieben:
void bewege(Saeule &von, Saelue &nach, Saeule &hilf, uint wieviele) { void bewege(Saeule &von, Saeule &nach, Saeule &hilf, uint wieviele) { if (wieviele>1) // Wenn mehr als 1 Scheibe: Auf Hilfsstapel umschichten bewege (von, hilf, nach, wieviele-1); verschiebe(von, nach); // Unterstes Element verschieben if (wieviele>1) // Und gegebenenfalls den Hilfsstapel zurückschieben bewege(hilf, nach, von, wieviele-1, darsteller); }
Und das war es auch schon fast. Ein bisschen Gerüst drumherum und die Mönche legen los:
#include<stack> using namespace std; typedef unsigned int uint; class Scheibe { private: uint dicke; public: Scheibe(uint dicke): dicke(dicke){} }; typedef std::stack<Scheibe> Saeule; void verschiebe(Saeule &von, Saeule &nach) { nach.push(von.top()); von.pop(); } void bewege(Saeule &von, Saeule &nach, Saeule &hilf, uint wieviele) { if (wieviele>1) bewege (von, hilf, nach, wieviele-1); verschiebe(von, nach); if (wieviele>1) bewege(hilf, nach, von, wieviele-1, darsteller); } int main() { // Der große Gott Brahma erschafft am Anfang des Universums drei Säulen und legt Scheiben auf eine davon (aber nicht 100, sondern hier nur 10). Saeule A,B,C; for (uint i=10; i>=1; --i) A.push(Scheibe(i)); // Und dann gibt er den Mönchen den Auftrag von A nach B umzuschichten: bewege(A,B,C,A.size()); }
Weiter mit der Grafik geht es nach der nächsten Maus.
-
-
So, zur Grafik: Wir müssen in Erfahrung bringen können, wie dick eine Scheibe ist, also erweitern wir unsere Klasse:
class Scheibe { private: uint dicke; public: Scheibe(uint dicke): dicke(dicke){} uint get_dicke() const{return dicke;} };
Weiterhin war ein Stack zwar eine gute Wahl für das Verschiebespiel, aber wenn wir eine ganze Säule darstellen wollen, müssen wir Zugriff auf alle Elemente haben. Nehmen wir stattdessen mal einen vector:
typedef std::vector<Scheibe> Saeule;
Dummerweise hat Stack ein etwas anderes Interface als vector. Deshalb müssen wir ein paar Sachen ändern (nichts wichtiges, nur die Namen der Methoden!). Deshalb vermeidet man in der Regel in C++ die Spezialcontainer wie stack und queue, sondern nimmt gleich einen der Standardcontainer wie vector, die dann auch ein weitgehend einheitliches Interface haben:
void verschiebe(Saeule &von, Saeule &nach) { nach.push_back(von.back()); von.pop_back(); } // ... for (uint i=10; i>=1; --i) A.push_back(Scheibe(i));
Nun zur Grafik: Nach jedem Verschiebevorgang wollen wir die Säulen dargestellt haben, also in der bewege-Funktion:
void bewege(Saeule &von, Saeule &nach, Saeule &hilf, uint wieviele) { if (wieviele>1) { bewege (von, hilf, nach, wieviele-1, darsteller); } verschiebe(von, nach); stelle_dar(A,B,C); if (wieviele>1) { bewege(hilf, nach, von, wieviele-1, darsteller); } }
Doch, oh Schreck, A, B und C gibt es in der Funktion gar nicht. Machen wir stattdessen mal wieder eine neue Klasse, die sich die Säulen merkt und gegebenenfalls darstellt:
class Darsteller { private: const Saeule &A,&B,&C; public: Darsteller(const Saeule &A, const Saeule &B, const Saeule &C): A(A), B(B), C(C){} void stelle_dar() const; };
Die stelle_dar-Funktion kannst du nach deinem Geschmack gestalten. Die Grundstruktur ist, dass du die drei Säulen durchläufst und die Scheiben darstellst:
void Darsteller::stelle_dar() const { // Säule A: for (Saule::const_iterator it = A.begin(); it != A.end(); ++it) { // Darstellung der Scheibe *it } // Säule B: for (Saule::const_iterator it = B.begin(); it != B.end(); ++it) { // Darstellung der Scheibe *it } // Säule C: for (Saule::const_iterator it = C.begin(); it != C.end(); ++it) { // Darstellung der Scheibe *it } }
Ich bin mal ganz billig und gebe nur Text aus:
void Darsteller::stelle_dar() const { std::cout<<"Säule A:"; for (Saeule::const_iterator it = A.begin(); it != A.end(); ++it) { cout<<' ' <<it->get_dicke(); } cout<<'\n'; std::cout<<"Säule B:"; for (Saeule::const_iterator it = B.begin(); it != B.end(); ++it) { cout<<' ' <<it->get_dicke(); } cout<<'\n'; std::cout<<"Säule C:"; for (Saeule::const_iterator it = C.begin(); it != C.end(); ++it) { cout<<' ' <<it->get_dicke(); } cout<<'\n'; cout<<'\n'; }
Man sieht sofort: Selbst einfachste Textausgabe ist gegenüber einer gut geschriebenen Programmlogik länglich und umständlich.
Das vollständige Programm:
#include<vector> #include<iostream> using namespace std; typedef unsigned int uint; class Scheibe { private: uint dicke; public: Scheibe(uint dicke): dicke(dicke){} uint get_dicke() const {return dicke;} }; typedef std::vector<Scheibe> Saeule; void verschiebe(Saeule &von, Saeule &nach) { nach.push_back(von.back()); von.pop_back(); } class Darsteller { private: const Saeule &A,&B,&C; public: Darsteller(const Saeule &A, const Saeule &B, const Saeule &C): A(A), B(B), C(C){} void stelle_dar() const; }; void Darsteller::stelle_dar() const { std::cout<<"Säule A:"; for (Saeule::const_iterator it = A.begin(); it != A.end(); ++it) { cout<<' ' <<it->get_dicke(); } cout<<'\n'; std::cout<<"Säule B:"; for (Saeule::const_iterator it = B.begin(); it != B.end(); ++it) { cout<<' ' <<it->get_dicke(); } cout<<'\n'; std::cout<<"Säule C:"; for (Saeule::const_iterator it = C.begin(); it != C.end(); ++it) { cout<<' ' <<it->get_dicke(); } cout<<'\n'; cout<<'\n'; } void bewege(Saeule &von, Saeule &nach, Saeule &hilf, uint wieviele, const Darsteller &darsteller) { if (wieviele>1) { bewege (von, hilf, nach, wieviele-1, darsteller); } verschiebe(von, nach); darsteller.stelle_dar(); if (wieviele>1) { bewege(hilf, nach, von, wieviele-1, darsteller); } } int main() { // Der große Gott Brahma erschafft am Anfang des Universums drei Säulen und legt Scheiben auf eine davon (aber nicht 100, sondern wir fragen ihn persöhnlich). Saeule A,B,C; cout<<"Oh großer Brahma, wieviele Scheiben sollen deine Mönche verschieben?\n"; uint anzahl; cin >> anzahl; cout<<'\n'; for (uint i=anzahl; i>=1; --i) A.push_back(Scheibe(i)); // Der große Gott Brahme muss sich auch um nervige Darstellung kümmern. Die Pocken über die Aufgabenstellung! Darsteller darsteller(A,B,C); darsteller.stelle_dar(); // Und dann gibt er den Mönchen den Auftrag von A nach B umzuschichten: bewege(A,B,C,A.size(), darsteller); }
edit: Das Ergebnis seht ihr nach der nächsten Maus
-
@padreigh: Ja, da war noch ein Fehler drin, editiert.
Und so sieht das dann beispielsweise aus:
Oh großer Brahma, wieviele Scheiben sollen deine Mönche verschieben? 3 Säule A: 3 2 1 Säule B: Säule C: Säule A: 3 2 Säule B: 1 Säule C: Säule A: 3 Säule B: 1 Säule C: 2 Säule A: 3 Säule B: Säule C: 2 1 Säule A: Säule B: 3 Säule C: 2 1 Säule A: 1 Säule B: 3 Säule C: 2 Säule A: 1 Säule B: 3 2 Säule C: Säule A: Säule B: 3 2 1 Säule C:
edit: Der Darsteller ist übrigens ein gutes Beispiel für etwas, wo man lieber ein Singleton (ein einzigartiges globales Objekt) gemacht hätte, aber ich wollt's mal nicht übertreiben.
-
Also erstmal vielen vielen Dank für die Hilfe.
Leider gibt es Sachen, die ich noch nicht so ganz verstehe, gerade bei Klassen.
Vielleicht könntest du sie mir erklären:class Scheibe { private: uint dicke; public: Scheibe(uint dicke): dicke(dicke){} uint get_dicke() const {return dicke;} };
Was genau sagt mir jetzt die Zeile Scheibe(uint dicke): dicke(dicke){} ?
Typedef kenne ich auch noch nicht, aber ich glaube es spart einfach an Platz, oder? Man sagt typedef unsigned int nenne ich jetzt nur noch uint. Richtig?
Des Weiteren verstehe ich etwas in folgendem Abschnitt nicht:
typedef std::vector<Scheibe> Saeule; void verschiebe(Saeule &von, Saeule &nach) { nach.push_back(von.back()); von.pop_back(); }
Was ist nach.push_back und von.pop_back?
Und die Typedef Zeile bleibt mir schleierhaft.
Oder ist das alles schon vorimplementiert als Vektor mit seinen Befehlen in der Bibliothek?Zu guter letzt verstehe ich diese Zeile nicht:
for (Saule::const_iterator it = A.begin(); it != A.end(); ++it)
Ich finde es echt super, dass du es mir so ausführlich erklärst
Vielen Dank dafür!
-
http://www.lmgtfy.com/?q=c%2B%2B+vector
Gleich der erste dicke Treffer
-
Hilbert schrieb:
Also erstmal vielen vielen Dank für die Hilfe.
Leider gibt es Sachen, die ich noch nicht so ganz verstehe, gerade bei Klassen.
Vielleicht könntest du sie mir erklären:class Scheibe { private: uint dicke; public: Scheibe(uint dicke): dicke(dicke){} uint get_dicke() const {return dicke;} };
Was genau sagt mir jetzt die Zeile Scheibe(uint dicke): dicke(dicke){} ?
Das ist ein sogenannter Konstruktor mit Initialisierungsliste. Die Stichworte sollten zum Googeln reichen.
Typedef kenne ich auch noch nicht, aber ich glaube es spart einfach an Platz, oder? Man sagt typedef unsigned int nenne ich jetzt nur noch uint. Richtig?
Ja, hier habe ich das aus Schreibfaulheit gemacht. Der eigentliche Zweck kommt unten.
Des Weiteren verstehe ich etwas in folgendem Abschnitt nicht:
typedef std::vector<Scheibe> Saeule; void verschiebe(Saeule &von, Saeule &nach) { nach.push_back(von.back()); von.pop_back(); }
Was ist nach.push_back und von.pop_back?
Und die Typedef Zeile bleibt mir schleierhaft.Dies ist der eigentliche Zweck von typedef: Namen zentral definieren. Ich kann im ganzen Programm
Saelue
schreiben, wenn ich eigentlichstd::vector<Scheibe>
meine. Dadurch kann ich das wofür Saeule steht mit minimalem Aufwand auswechseln, wenn der Bedarf besteht. Genauso wie ich ja bei der Herleitung des Programms von stack auf vector gewechselt bin.Oder ist das alles schon vorimplementiert als Vektor mit seinen Befehlen in der Bibliothek?
Genau. vector ist eine ganz wichtige Klasse der Standardbibliothek (genauer: ein Klassentemplate, aber das sagt dir vermutlich noch nichts). Es ist eine Ansammlung von Werten die man flexibel erweitern kann und über ihren Namen und die Nummer ansprechen kann:
std::vector<int> foo(6);
hat zum Beispiel 6 Elemente vom Typ int, die überfoo[0]
bisfoo[5]
ansprechbar sind. Die Methodepush_back
fügt hinten ein Element an,pop_back
löscht das hinterste Element.Zu guter letzt verstehe ich diese Zeile nicht:
for (Saule::const_iterator it = A.begin(); it != A.end(); ++it)
Dies ist ein anderes wichtiges Konzept der Standardbibliothek: Iteratoren
Da Saeule bei mir ein vector ist, hätte ich auch folgendes machen können:for (int i=0; i<A.size(); ++i) // stelle A[i] dar
Und das wäre auch vollkommen korrekt für vector, weil vector auf jedes beliebige Element zugreifen kann, wenn man ihm die Nummer des Elements vorgibt. Aber wir wollen flexibel bleiben und eventuell vector durch etwas anderes ersetzen, wenn Bedarf besteht. Etwas was vielleicht nicht Zugriffe wie A[i] kennt, zum Beispiel eine
std::list
(so ähnlich wie vector, aber intern anders organisiert, wodurch gewisse Aktionen schneller oder langsamer sind als bei vector, beispielsweise ist Zugriff auf das i-te Element so langsam, dass es gar nicht angeboten wird, dafür ist Einfügen in der Mitte viel schneller als bei vector). Wir brauchen bei der gezeigten Schleife auch gar nicht immer auf das i-te Element zuzugreifen, sondern wir wollen immer bei jedem Schleifendurchgang auf das nächste Element zugreifen, bis wir am Ende angelangt sind. Iteratoren sind eine allgemeine Schnittstelle um Container schrittweise durchzugehen, eine Aufgabe die sehr häufig vorkommt. Die Iteratoren werden von allen Containern der Standardbibliothek angeboten (außer Spezialcontainern wie stack, die bewusst darauf verzichten). Und wenn man selbst Containerklassen schreibt, sollte man auch Iteratoren dafür anbieten. Das heißt ich könnte den vector gegen irgendeinen Container austauschen, ohne an dem Programm irgendwas zu ändern, weil ich auf die Spezialeigenschaft des vectors (Zugriff a laA[i]
) verzichtet habe und stattdessen das abstraktere Konzept der Iteratoren benutzt habe.
-
Habe mal probiert dein Klassenprogramm in mein Funktionen&Array-Programm zu übertragen.
Aber ich schaffe es nicht..Ich habe die Arrays gegeben:
int Stab_1[AnzahlderScheiben]; int Stab_2[AnzahlderScheiben]; int Stab_3[AnzahlderScheiben];
So sieht meine Babelfunktionen aus:
void babel(int Scheiben, int von, int nach, int Hilf) { if (Scheiben == 0) return; babel(Scheiben-1,von,Hilf,nach); bewege (von,nach); zeichne(); babel(Scheiben-1,Hilf,nach,von); }
Das Problem habe ich mit
void bewege(int von, int nach) { }
Hier muss ich mit den Arrays arbeiten, leider geht das immer in die Hose.
Könnt ihr mir hier helfen?Die Funktion zeichne () habe ich.
Vielen,vielen Dank.
-
Wie stellt sich bei deinen Arrays denn dar, welche Scheiben auf einem Stab sind?
Gehe ich Recht in der Annahme, dass du dies selber nicht so genau weißt? Hier liegt dann nämlich die Wurzel deines Problems.
-
Stab_1: {5, 4, 0, 0, 0}
Stab_2: {3, 2, 1, 0, 0}
Stab_3: {0, 0, 0, 0, 0}
Stab_array: {{5, 4, 0, 0, 0},
{3, 2, 1, 0, 0},
{0, 0, 0, 0, 0}}
sieht so aus:
| | |
| | |
| <|> |
<<<<|>>>> <<|>> |
<<<<<|>>>>> <<<|>>> |
-------------------------------------
-
Dann wirst du dir entweder merken müssen, wo die Spitze ist (hier bietet sich wieder eine Klasse an oder eben gleich std::vector, welcher das sowieso schon macht) oder du musst immer die Spitze suchen. Und dann tauscht du.
-
Wie suche ich denn die Spitze?
Dann muss ich doch eine neue Funktion getSpitze() schreiben oder?
also void getspitze()
und da die kleinste zahl aus dem stab suchen.
Aber wie?