Aufzugsanzeige
-
Dann ist dir schwer zu helfen. Eine queue oder ähnliches selber programmieren ist viel zu schwer für deinen Kenntnisstand. Benutzen darfst du die fertige std::queue vermutlich auch nicht.
Überhaupt: Wahrscheinlich macht ihr gar kein C++. Ihr benutzt ja schon mindestens einmal irgendeine Art von GUI-Framework. Welches? Vielleicht findet sich dort Hilfe.
-
SeppJ schrieb:
Benutzen darfst du die fertige std::queue vermutlich auch nicht.
Doch doch, wir dürfen alles benutzen, so lange wir auch verstehen, wie es funktioniert.
SeppJ schrieb:
Wahrscheinlich macht ihr gar kein C++.
was kann man denn mit TurboC++ bzw. C++builder 6 noch programmieren?
-
Barnibas schrieb:
Kennt da zufällig jemand eine Möglichkeit, die dafür sorgt, dass erst die ereignisroutune des einen Knopfes und dann die des nächsten Knopfes ausgeführt wird?
Soll das wirklich so gemacht werden?
Wenn du in Stockwerk 1 bist und 3 und dann 2 drückst, soll er dann wirklich erst nach 3 und dann zurück nach 2?
Ein guter Aufzug würde wohl in 2 halten und dann erst nach 3.
Das könntest du dann auch ohne Standardbibliothek über ein Stockwerk-Array oder sowas machen.
-
Barnibas schrieb:
Der Grundquellcode steht schon, das heist der "Aufzug" fährt hoch und runter.
Hast du eine Variable, die die aktuelle Position des Aufzugs repräsentiert? Falls nicht, fährt da gar nichts. Dann hast du keine Aufzugsteuerung modelliert, sondern die Simulation einer Aufzugsteuerung.
-
Jockelx schrieb:
Das könntest du dann auch ohne Standardbibliothek über ein Stockwerk-Array oder sowas machen.
Ich hab mir gedacht so wie du es sagst wär es schwieriger, aber wenn du mir das erklären kannst, oder mir tipps geben kannst, mach ichs natürlich so

MFK schrieb:
Hast du eine Variable, die die aktuelle Position des Aufzugs repräsentiert?
Ja hab ich. Sobald ich daheim bin, poste ich hier den kompletten wa uellcode rein. Soll ich den einfach hier rein kopieren oder gibts hier ein tool oder sowas dafür?
-
Je nach Größe einfach Copy&Paste. Aber mehr als naja 200-300 Zeilen sind zuviel.
Dann musst du aufs Wesentliche reduzieren.
-
So hier kommt dann mal der bisherige Quellcode (ich hab immer von linie zu linie genommen, da ich glaube, das liest sich besser) :
Die Variable, die die höhe des Aufzugs anzeigt:
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;int h;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
h = 1; //Damit der Aufzug im EG startet
}
//---------------------------------------------------------------------------Der Timer, der die Position anzeigen lässt:
//---------------------------------------------------------------------------
void __fastcall TForm1::TimerAllgTimer(TObject *Sender)
{
pnlUG->Visible = false;
pnlEG->Visible = false;
pnl1->Visible = false;
pnl2->Visible = false;
pnl3->Visible = false;
pnl4->Visible = false;switch ((h)) {
case 0: pnlUG->Visible = true;
break;
case 1: pnlEG->Visible = true;
break;
case 2: pnl1->Visible = true;
break;
case 3: pnl2->Visible = true;
break;
case 4: pnl3->Visible = true;
break;
case 5: pnl4->Visible = true;
break;
default:
break;
}
}
//---------------------------------------------------------------------------Einer der Buttons (es ändert sich immer nur der Timername) :
//---------------------------------------------------------------------------void __fastcall TForm1::btn3Click(TObject *Sender)
{
timer3->Enabled = true;
}
//---------------------------------------------------------------------------Der dazugehörige Timer (hier ändern sich ebenfalls nur die Namen der Komponente und an welcher case-Position sie stehen):
//---------------------------------------------------------------------------void __fastcall TForm1::timer3Timer(TObject *Sender)
{
switch ((h)) {
case 0: h = h + 1;
break;
case 1: h = h + 1;
break;
case 2: h = h + 1;
break;
case 3: h = h + 1;
break;
case 4: timer3->Enabled = false;
break;
case 5: h = h - 1;
break;
default:
break;
}
}
//---------------------------------------------------------------------------Ich hoffe, ihr könnt alles daraus lesen, wenn nicht, sagt bescheind!!
-
Ehrlich gesagt: Das ist Mist. Gaaaaaaanz großer Mist. Da fehlt Abstraktion. Gaaaaaanz viel Abstraktion. Dann könnte man auch einfach neue Features einbauen. Aber wenn du jede einzelne Aktion von jedem einzelnen Button einzeln programmiert hast und sogar jede einzelne Änderung von h für jeden Einzelfall einzeln programmiert ist, dann muss auch jedes neue Feature an jeder dieser Stellen einfließen.
Daher ein allererster Plan zur Verbesserung:
- Schreib Funktionen! Allgemeine Funktionen! Anstatt 5 verschiedene Funktionen um den Aufzug in 5 verschiedene Stockwerke fahren zu lassen, hast du nur noch eine Funktion, die den Aufzug in das N'te Stockwerk fahren lässt. Anstatt in dieser Funktion jeden Einzelfall zu switch'en betrachtest du nur noch die Fälle "muss hochfahren", "muss runterfahren", "ist da".
- Entsprechend vereinfachen sich die Reaktionen auf die Ereignisse: Anstatt 5 verschiedene Reaktionen einzeln zu Programmieren gibt es eine zentrale Reaktion auf das Drücken eines Fahrstuhlknopfes, die dann den Fahrstuhl in das entsprechende Stockwerk schickt.
- Wenn du dann irgendwann so weit bist (das obige ist eine Menge Arbeit und du wirst sicherlich eine Menge über Programmierung dabei lernen), dann kannst du in dieser Ereignisverwaltung ansetzen und dort die verschiedenen Knopfdrücke in einer Queue sammeln. Oder dir später sogar mal Gedanken machen, wie der Aufzug cleverer gesteuert werden kann (siehe Jockelx' Hinweis auf der ersten Seite).
-
An funktionen habe ich bisher noch gar nicht gedacht. Danke für den tipp! Ich setzt mich gleich mal ran und versuch es so zu machen, wie du es gesagt hast. Aber was meinst du mit abstraktion?
-
Barnibas schrieb:
Aber was meinst du mit abstraktion?
Anstatt für jedes Problem eine einzelne Lösung zu entwickeln, denkst du über die Gemeinsamkeiten der Probleme nach und entwickelst eine Allumfassende Lösung für alle Problemstellungen gleichzeitig.
Hier hattest du beispielsweise die Probleme
-"Fahre in das erste Stockwerk"
-"Fahre in das zweite Stockwerk"
-"Fahre in das dritte Stockwerk"
-"Fahre in das vierte Stockwerk"
-"Fahre in das fünfte Stockwerk"In dem Code, den du uns gezeigt hast, hast du für alle diese Probleme eine einzelne Lösung erzeugt: timer1Timer, timer2Timer, timer3Timer, timer4Timer und timer5Timer. Genauer noch hast du sogar jeweils innerhalb dieser Teilproblemlösungen noch kleinere Teilprobleme gehabt, zum Beispiel innerhalb von timer3Timer:
-"Fahre vom 1. Stockwerk in das 3.Stockwerk"
-"Fahre vom 2. Stockwerk in das 3.Stockwerk"
-"Fahre vom 3. Stockwerk in das 3.Stockwerk"
-"Fahre vom 4. Stockwerk in das 3.Stockwerk"
-"Fahre vom 5. Stockwerk in das 3.Stockwerk"
Die hast du auch alle einzeln gelöst (deine switch-Konstruktion).Meinst du nicht, dass man das auch hätte allgemeiner lösen können? Zum Beispiel indem man das Problem
"Fahre in das N. Stockwerk"
löst? Dann bräucht man nämlich nur noch diese eine Lösung, weil diese alle 5 Teilprobleme oben umfasst. Besser noch: Wenn jemals ein 6. Stockwerk oder ein Keller hinzukommt, dann funktioniert die allgemeine Lösung für das N. Stockwerk immer noch unverändert! Wenn du jedoch die 5 Speziallösungen benutzt, dann müsstest du in diesem Fall eine weitere Speziallösung für den 6.Stock oder den Keller hinzufügen.
-
Den grundgedanken von deinem vorschlag verstehe ich, allerding hab ich so gar keine ahnung wie ich das umsetzen soll, zu mindest mit meinem wissensstand. Am anfang wollte ich z.b. eine funktion machen, die einfach so lange -1 oder +1 macht, bis der gewünschte wert erreicht ist. Allerdings hab ich dann das problem: wie mach ich es, dass der computer nicht in seiner rechengeschwindig rechnet, sondern nach jedem abziehen oder hinzufügen 1sec wartet und wie sag ich dem computer, dass er hinzufügen oder abziehen soll?
Und stockwerke hab ich im moment von UG - 4.OG
-
Ich hab das ganze jetzt mal Probiert und nach einigen Problemen auch hingekriegt.
das ganze sieht dann jetzt so aus:
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Test_u.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; int z, p; //Position und Ziel des Aufzugs //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { z = 1; //Damit der Aufzug im EG anfängt p = 1; //Damit der Aufzug im EG anfängt } //--------------------------------------------------------------------------- int plus_eins(int p) { p = p + 1; return p; } //--------------------------------------------------------------------------- int minus_eins(int p) { p = p - 1; return p; } //--------------------------------------------------------------------------- void __fastcall TForm1::timerFahrtTimer(TObject *Sender) { if (z == p) { timerFahrt->Enabled = false; } else if (z > p) { p = plus_eins(p); } else p = minus_eins(p); } //--------------------------------------------------------------------------- void __fastcall TForm1::timerAnzeigeTimer(TObject *Sender) { pnlUG->Visible = false; pnlEG->Visible = false; pnl1->Visible = false; pnl2->Visible = false; pnl3->Visible = false; pnl4->Visible = false; switch ((p)) { case 0: pnlUG->Visible = true; break; case 1: pnlEG->Visible = true; break; case 2: pnl1->Visible = true; break; case 3: pnl2->Visible = true; break; case 4: pnl3->Visible = true; break; case 5: pnl4->Visible = true; break; default: break; } } //--------------------------------------------------------------------------- void __fastcall TForm1::btnUGClick(TObject *Sender) { z = 0; timerFahrt->Enabled = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::btnEGClick(TObject *Sender) { z = 1; timerFahrt->Enabled = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::btn1Click(TObject *Sender) { z = 2; timerFahrt->Enabled = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::btn2Click(TObject *Sender) { z = 3; timerFahrt->Enabled = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::btn3Click(TObject *Sender) { z = 4; timerFahrt->Enabled = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::btn4Click(TObject *Sender) { z = 5; timerFahrt->Enabled = true; } //---------------------------------------------------------------------------Das ist jetzt der komplette code von oben bis unten. kann man damit jetzt mehr anfangen? Oder fehlt da noch was?
Edit:
Theoretisch könnte ich die Funktionen auch weglassen und bei//--------------------------------------------------------------------------- void __fastcall TForm1::timerFahrtTimer(TObject *Sender) { if (z == p) { timerFahrt->Enabled = false; } else if (z > p) { p = plus_eins(p); } else p = minus_eins(p); } //---------------------------------------------------------------------------p = p + 1;bzw.
p = p - 1;schreiben oder?
-
Zum Erhöhen und Erniedrigen um 1:
Ja, das ist ungeheuer umständlich bei dir.x = x + 1; x += 1; ++x;machen alle das gleiche. Nimm das letzte.
Zum Code:
Ja, damit kann man doch was anfangen. Jetzt machen wir mal in Babyschritten weiter:
-Das Abschicken des Fahrstuhls ist nicht sehr schön (Zeile 75 bis Ende). Da hast du wieder 6x den gleichen Code. Abstraktion! Schreibe eine Funktion, die ein Stockwerk als Argument entgegen nimmt und den Aufzug losschickt. Deine Ereignisbehandlungsfunktionen rufen dann diese Funktion mit dem passenden Stockwerk auf. (Letzteres darfst du meinetwegen 6x schreiben, wenn du noch nicht weißt, wie das besser geht)
-Prüfe, ob dein Programm noch funktioniert.
-Du kannst derzeit ja prüfen, ob der Aufzug fährt oder nicht (wenn dein timer enabled ist oder nicht). Prüfe in deiner Fahrstuhlabschickfunktion, die du oben geschrieben hast, ob der Aufzug derzeit fährt oder nicht. Falls er fährt, ignoriere das Kommando.
-Prüfe, ob dein Programm noch funktioniert. Nun sollte es nicht mehr möglich sein, während der Fahrstuhl fährt ein neues Kommando zu geben.
-Jetzt wird es kompliziert, weil jetzt etwas neues kommt. Ich nehme mal an, dass du dir die Grundlagen der queue (push, pop, front, size) mal angesehen hast. Ersetze dein Zielstockwerk z durch eine std::queue<int> (die queue ist zu Anfang leer, entferne also Zeile 17). Denk dran, dass du den Header <queue> einbinden musst.
-Nun müssen an der Programmlogik Änderungen vorgenommen werden:
* Wenn ein Knopf gedrückt wird, wird das Zielstockwerk an die queue angefügt (push). Dein Fahrstuhl wird ggf. aktiviert, falls er es noch nicht ist.
* Wenn der Fahrstuhl aktiviert ist, dann fährt er zum vordersten Element (front) der queue.
* Wenn der Fahrstuhl angekommen ist, dann löscht er das vorderste Element (pop). Falls noch Elemente in der queue sind (size), dann fährt er weiter, ansonsten deaktiviert er sich
-Vermutlich wirst du für den Schritt eine ganze Weile brauchen. Und zwischendurch viel falsch machen. Frag zur Not nach (aber erst, nachdem du nicht mehr weiter kommst. Selber versuchen Probleme zu lösen, lehrt Probleme selber lösen zu können
. Guck dir meine Tipps an, lies die verlinkten Referenzen zur queue, schau dir die Beispiele an.)
-Prüfe dein Programm, es sollte nun so funktionieren, wie du es in deinem allerersten Beitrag gefragt hast.
-
Ich werde jetzt deine Liste Schritt für Schritt abarbeitn. Danke schonmal dafür!
allerdings hab ich schon wieder keine ahnung wie ich den Teil umsetzen soll:
SeppJ schrieb:
Schreibe eine Funktion, die ein Stockwerk als Argument entgegen nimmt und den Aufzug losschickt. Deine Ereignisbehandlungsfunktionen rufen dann diese Funktion mit dem passenden Stockwerk auf.
Ich verseth das Ganze so:
Ich soll eine Funktion schrieben, die den Wert "z" entgegen nimmt und den "timerFahrt" startet. Aller dings sehe ich darin keinen großen sinn, weil ich dann in der Ereignisroutine jedes Buttons die Funktion aufrufen müsste, welche dann nichts weiter macht als den Timer zu starten. Oder hab ich dass schon wieder falsch verstanden?Und wie der Teil gemeint ist, weis ich auch nicht:
SeppJ schrieb:
Du kannst derzeit ja prüfen, ob der Aufzug fährt oder nicht (wenn dein timer enabled ist oder nicht). Prüfe in deiner Fahrstuhlabschickfunktion, die du oben geschrieben hast, ob der Aufzug derzeit fährt oder nicht. Falls er fährt, ignoriere das Kommando.
Wie Prüfe ich, ob der Aufzug fährt? Während der Laufzeit oder wie ist das gemeint?
-
Barnibas schrieb:
Ich soll eine Funktion schrieben, die den Wert "z" entgegen nimmt und den "timerFahrt" startet. Aller dings sehe ich darin keinen großen sinn, weil ich dann in der Ereignisroutine jedes Buttons die Funktion aufrufen müsste, welche dann nichts weiter macht als den Timer zu starten. Oder hab ich dass schon wieder falsch verstanden?
Doch das hast du richtig verstanden. Das gibt dir hinterher einen zentralen Angriffspunkt, da du die intelligente Aufzugsteuerung nur noch an einem Punkt einbringen brauchst, anstatt an sechs verschiedenen Punkten. Ja, deine Buttoneventhandler rufen dann alle diese Funktion auf die gleiche Weise auf. Es wäre daher natürlich wesentlich eleganter, wenn die Events gleich die richtige Funktion aufrufen würden. Aber da ich dein Framework nicht kenne, kann ich dir nicht sagen ob und wie das geht. Wenn du weißt, wie es geht, dann tu es, ansonsten musst du eben für jeden Button einen leicht veränderten Funktionsaufruf schreiben.
Und wie der Teil gemeint ist, weis ich auch nicht:
SeppJ schrieb:
Du kannst derzeit ja prüfen, ob der Aufzug fährt oder nicht (wenn dein timer enabled ist oder nicht). Prüfe in deiner Fahrstuhlabschickfunktion, die du oben geschrieben hast, ob der Aufzug derzeit fährt oder nicht. Falls er fährt, ignoriere das Kommando.
Wie Prüfe ich, ob der Aufzug fährt? Während der Laufzeit oder wie ist das gemeint?
Wenn der Aufzug fahren soll, dann aktivierst du doch deinen Timer:
timerFahrt->Enabled = true;Und wenn der Aufzug angekommen ist, schaltest du ihn aus:
if (z == p) { timerFahrt->Enabled = false; }Daraus folgt: Wenn der Timer aktiviert ist, fährt der Aufzug gerade. Du kannst natürlich auch noch eine zusätzliche bool-Variable "bereit" oder "faehrt" einführen, falls dir das lieber ist.
-
Jetzt kapier ich gar nichts mehr.
1. Die Funktion ist also nur da, um das ganze etwas eleganter wirken zu lassen....so hab ich das verstanden.
2. Brauch ich doch im Moment gar nichts prüfen, weil es doch eigentlich funktioniert (dass der Aufzug fährt oder nicht).
3. Was ist ein Framework, bzw. wo finde ich das bei mir?
-
Barnibas schrieb:
Jetzt kapier ich gar nichts mehr.
1. Die Funktion ist also nur da, um das ganze etwas eleganter wirken zu lassen....so hab ich das verstanden.Nicht nur etwas eleganter. Jetzt hast du als Steuerungslogik bloß zwei Zeilen:
void __fastcall TForm1::btn2Click(TObject *Sender) { z = 3; timerFahrt->Enabled = true; }Und diese Zeilen hast du 6x. Jetzt willst du deine Steuerlogik aber erweitern. Dazu müsstest du 6x Änderungen vornehmen. Nicht sehr gut. Daher lagerst du die Steuerlogik besser aus und erweiterst sie dann bloß noch an einer Stelle.
2. Brauch ich doch im Moment gar nichts prüfen, weil es doch eigentlich funktioniert (dass der Aufzug fährt oder nicht).
Das ist ein Zwischenschritt. Du willst schließlich dass der Aufzug in Zukunft anders reagiert, je nachdem, ob er schon fährt (dann soll er erst ankommen und dann zum neuen Ziel weiterfahren) oder ob er wartet (dann soll er gleich losfahren). Ein erster Schritt ist daher überhaupt erst die Unterscheidung auf "fährt" und "wartet" einzubauen.
3. Was ist ein Framework, bzw. wo finde ich das bei mir?
Na, dein C++-Builder Krams. Also deine ganzen Buttons und Forms. Dafür gibt es hier auch ein Forum, wenn du Fragen hast, wie man das benutzt:
http://www.c-plusplus.net/forum/f2
Die wenigsten hier im Forum für reines C++ (so auch ich), werden sich damit auskennen. An sich hatte deine Frage aber auch nicht mit der Benutzung des C++-Builders zu tun, daher war es schon richtig, hier zu fragen.
-
Ahhhh jetzt hab ich es verstanden...glaub ich zu mindestens. Du bist nicht zufällig ein Lehrer oder?

SeppJ schrieb:
Ein erster Schritt ist daher überhaupt erst die Unterscheidung auf "fährt" und "wartet" einzubauen.
Wenn ich das richtig verstanden habe, meinst du so etwas:
//----------------------------------- void funktion_sowieso(bool zustand, int z, int p) if (z == p) zustand = false; //Aufzug steht else zustand = true; //Aufzug fährtwobei "zustand" eine neue Variable ist und anzeigt, ob der Aufzug fährt oder steht.
-
Ich dachte eher so:
void __fastcall TForm1::timerFahrtTimer(TObject *Sender) { if (z == p) { timerFahrt->Enabled = false; faehrt = false; } else if (z > p) { p = plus_eins(p); } else p = minus_eins(p); } // ... void __fastcall TForm1::lassAufzugFahren(int wohin) { z = wohin; faehrt = true; timerFahrt->Enabled = true; } // ... void __fastcall TForm1::btnUGClick(TObject *Sender) { lassAufzugFahren(0); } // und noch 5x das gleiche mit anderen StockwerkenDas sollte (ungetestet) noch das gleiche tun wie dein derzeitiger Code (du musst natürlich noch den bool
faehrtund die MemberfunktionlassAufzugFahrenzuTForm1hinzufügen). Dann wäre der nächste Schritt mit der Prüfung:void __fastcall TForm1::lassAufzugFahren(int wohin) { if (! faehrt) { z = wohin; faehrt = true; timerFahrt->Enabled = true; } }Damit sollte dann der Effekt eintreten, dass der Aufzug blockiert, während er fährt und man nur Kommandos geben kann, wenn er steht. Der nächste Schritt wäre dann der komplizierte Schritt, bei dem die blockierten Kommandos stattdessen zwischengespeichert werden und dann nach der Ankunft ausgeführt werden.
-
SeppJ schrieb:
Ich dachte eher so:
das leuchtet mir ein.
allerdings fehlt da:
SeppJ schrieb:
void __fastcall TForm1::lassAufzugFahren(int wohin) { if (! faehrt) { z = wohin; faehrt = true; timerFahrt->Enabled = true; } }nicht noch ein else?