Wait for ButtonClick



  • Hallo

    Da du mit dem Builder arbeitest, ist dein Framework die VCL des Builders, die Klassenbibliothek die dir z.B. die ganzen Komponenten in der IDE bereitstellt.
    Damit gehört dieser Thread auch ins Builder-Subforum, wohin dich auch bald ein Mod verschieben wird.

    Was ich nicht verstehe ist: Sollen deine Funktionen nun unabhängig naheinander ausgeführt werden (dann benutzt TThread) oder vom User einzeln ausgelöst werden (dann einfach die OnClick-Events der Buttons nutzen)?

    bis bald
    akari



  • Nee, die Funktionen sollen alle automatisch nacheinander aufgerufen werden.
    Wenn die erste Funktion beendet ist, dann wird die nächste aufgerufen usw.
    Aber in jeder Funktion soll auf ein ButtonClick gewartet werden, damit die gerade aktive Funktion fortgesetzt werden kann, dann irgendwann zum Ende gelangt, die Programmsteuerung wieder main übergeben wird und die nächste Funktion aufgerufen wird usw.



  • #include <conio.h>
    int i, buttonzahl=13;
    while((i=getche())!=buttonzahl){ warten(); }
    

    Sicherlich net die beste Lösung aber funktioniert. Buttonzahl is einfach nur die ASCII Zahl des jeweiligen Buttons.



  • Hallo

    @effe : Nein, das bringt milo51 garnichts, da er ja nicht in der Konsole arbeitet, sondern in der VCL-GUI.

    @milo51 : Du must doch nur die einzelnen Teilfunktionen auf die zugehörigen Button-Clicks aufteilen und das jeweilige Zwischenergebnis in einer passenden Variable/Struktur zwischenspeichern. So das die jeweils folgende Funktion auf die Daten der vorhergehenden Funktion zugreifen kann.

    bi bald
    akari



  • int ButtonClicks = 0;
    
    .
    .
    .
    
    void ClickOnButton1()
    {
        ButtonClicks++;
        if(ButtonClicks>EndeDerFahnenStange)
            ButtonClicks = 0; //evetnuell auch einen Extra Flag setzen
        Auswerten(); //eventuell auch extern aufrufen
    }
    
    void Auswerten()
        switch(ButtonClicks)
        {
            case 1:
                func1();
                break;
            case 2:
                func2();
                break;
            case 3:
                func3();
                break;
        }
    }
    

    Und das ganze noch in ne Klasse kapseln, der man ein Objekt übergibt, in dem alle aufzurufenden Funktionen gespeichert sind 🙂



  • Irgendwie versteh ich das von euch beiden nicht ganz...
    Ich zeig mal den Code:

    //globale variablen
    int ansNumber = 0;
    int correctNum = 0;
    
    // Per Klick auf den Start Button fängt das ganze Programm an:
    void __fastcall TForm1::Button5Click(TObject *Sender)
    {
         quest("Wie heisst der Programmierer?", "Patrick", "Alex", "Holger",
               "Jesse", 1);
         quest("Was ist 1 + 1?", "1", "2", "3", "4", 2);  /* Diese 2. Funktion darf erst DANN aufgerufen werden, wenn auf ein Button geklickt wurde und das jeweilige Ergebnis überprüft wurde!*/
    }
    
    // aufgerufene Funktion
    void quest(AnsiString question, AnsiString ans1, AnsiString ans2,
               AnsiString ans3, AnsiString ans4, int correctNumber)
    {
         Form1->Label1->Caption = question;
         Form1->Label2->Caption = ans1;
         Form1->Label3->Caption = ans2;
         Form1->Label4->Caption = ans3;
         Form1->Label5->Caption = ans4;
         correctNum = correctNumber;
    
    }
    
    //Antwort Button
    void __fastcall TForm1::btnAns1Click(TObject *Sender)
    {
         ansNumber = 1;
         if (ansNumber == correctNum)
              {
                   ShowMessage("Richtig!");
              }
              else
                   if ((ansNumber != 0) && (ansNumber != correctNum))
                   {
                        ShowMessage("Falsch! Die richtige Antwort war Antwort "
                                    + IntToStr(correctNum));
                   }
    
    }
    


  • aaaaaaaaalsooo:
    Ich hab mal Zeit 😉

    Ich persönlich würde die Fragen in eine Struktur kapseln. Etwa so:

    struct FragenData
    {
        AnsiString frage;
        AnsiString antwort1;
        AnsiString antwort2;
        AnsiString antwort3; //Falls es nicht bei jeder Frage gleich viele Antwortmöglichkeiten gibt, empfehle ich std::vector<AnsiString>
        int richtigeAntwort;
        FragenData (AnsiString fr, AnsiString aw1, AnsiString aw2, AnsiString aw3, int awCorrect) //Konstruktor zum Initialisieren der Struktur FragenData
        {
            frage = fr;
            antwort1 = aw1;
            antwort2 = aw2;
            antwort3 = aw3;
            richtigeAntwort = awCorrect;
        }
    };
    

    Nun kannst du zum Beispiel folgende Initialisierung schreiben:

    #include <vector> //nötig um den Vector zu nutzen
    
    class TForm1 : public Form //Da ich nicht mit vcl programmiere, stimmt die Basisklasse wohl nicht!
    {
    private:
        std::vector<FragenData> vecFragenData; //Speicherung der Fragendaten
        int aktFrage; //Bei welcher Frage sind wir gerade?
        bool schonGestartet; //Spiel schon gestartet?
        //...
    public:
        void init(); //Initialisierung der Fragen
        void testeAntwort(FragenData fd, int antwort);
        void updateForm();
        //...
    };
    
    void TForm1::init()
    {
        vecFragenData.clear(); //Vector löschen
        vecFragenData.push_back(FragenData("Wie alt ist der Mond?", "Tot", "Häh?", "Älter als ich, glaub ich", 3));
        vecFragenData.push_back(FragenData("Gib mir ein U!", "U", "M", "B", 1));
       //Somit sind jetzt 2 Fragen in dem Vector "vecFragenData" gespeichert. Was ein Vector genau macht solltest du in einem Tutorial deiner Wahl nachlesen. Für den Anfang reicht es ihn als "besseres" Array zu betrachten, in den per push_back(...) Daten gespeichert werden können.
        aktFrage = 0; //Wir sind bei Frage 0
        schonGestartet = false; //noch net gestartet
    }
    
    void TForm1::updateForm()
    {
        if(schonGestartet && aktFrage < vecFragenData.size()) //testen ob schon gestartet wurde und ob wir noch Fragen im Vector haben.
        {
            FragenData fd = vecFragenData[aktFrage]; //Nun lesen wir aus dem Vector den 0. (also den 1.) Eintrag aus.
            quest(fd.frage, fd.antwort1, fd.antwort2, fd.antwort3, fd.richtigeAntwort); //und übergeben die gepeicherten Daten der Funktion quest
        }
    
    }
    

    StartButton:

    void __factcall TForm1::Button5Click(TObject *Sender)
    {
        init(); //Fragen in den Vector schreiben (Könnte man auch bei Form_Load machen
        aktFrage = 0;
        schonGestartet = true;
        updateForm(); //aktuelle Frage in die Textboxen schieben
    }
    

    AntwortButton:

    void __fastcall TForm1::btnAns1Click(TObject *Sender)
    {
        if(schonGestartet)
            testeAntwort(vecFragenData[aktFrage], 1);
    }
    
    //Button2
    void __fastcall TForm1::btnAns2Click(TObject *Sender)
    {
        if(schonGestartet)
            testeAntwort(vecFragenData[aktFrage], 2);
    }
    
    void TForm1::testeAntowrt(FragenData fd, int antwort)
    {
        if(fd.richtigeAntwort == antwort)
            MessageBox("Jawohl, du bists!");
        else
            MessageBox("Schwach!");
    
        aktFrage++; //Zur nächsten Frage übergehen
        updateForm(); //Nächste Frage in die Textboxen schreiben.
    }
    

    So. Ich hoffe das war einigermassen verständlich. Der Vorteil an dieser Methode ist, dass du deine Fragen völlig dynamisch laden kannst und auch im Design deiner Form unabhängig von der Anzahl der Fragen bist. Und später kann man das ganze dann auch noch so erweitern, dass man die Fragen extern (Datei) speichert.

    P.S.: Ich hab das eben per Hand geschrieben ohne zu compilieren, also sind wohl einige Syntaxfehler drin. Aber ich denk das kriegst du hin 🙂

    Hier übrigens was zum vector:
    http://www.msoe.edu/eecs/ce/courseinfo/stl/vector.htm



  • Ah, danke erstmal 🙂
    Hm das ist komisch, wenn ich

    vecName.push_back(FragenData(argumente));
    

    schreibe, dann wird der Konstruktor der Klasse dabei aufgerufen??!

    Ich dachte erst, wenn man auf das Element zugreift, z.B. mit vecName[0]....



  • Richtig. Der Konstruktor wird aufgerufen, falls ein Objekt einer Klasse erstellt wird. Deshalb auch der Name Konstruktor - von konstruieren *g*. Das selbe gilt für den Destruktor. Er wird aufgerufen, falls ein Objekt zerstört wird. Also entweder explizit mit new oder eben, falls es sich nicht mehr innerhalb seines Gültigkeitsbereiches befindet.



  • Jo das wusste ich, mir war grad nur nicht klar, dass der auch beim push_back shcon aufgerufen wird^^

    Verdammt, das ist dumm...muss ich alles wieder umplanen^^

    Ach ja und ich glaube, du meinst mit "delete" 😉



  • Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum VCL/CLX (Borland C++ Builder) 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