Rekursive Randomize Funktion



  • Braunstein schrieb:

    Hallo,

    Bevor du Zufall() neu aufrufst solltest du deine bool Variablen (_0, _1 etc.) auf false zurücksetzen, sonst kommst du in eine endlose Rekursion.

    Ciao

    Problem ist an ganz anderer stelle:

    es kann einfach vorkommen das random 1000x mal nur 1 oder 2 zurückgibt. setzte dein intervall auf z.b. 100 dann ist die warscheinlichkeit, dass die gleich zahl immer wieder erscheint viel nidrieger.



  • @Jansen: O.K., Randomize() initializiere ich jetzt im FormCreateEvent.

    @Xqgene: Wenn ich den Intervall z.B. auf 100 setzte, muss ich ja zig mal
    auf den Button nächste Frage klicken, bis endlich mal eine von den 4(!) Fragen angezeigt wird...



  • MastaFlasH schrieb:

    Wenn ich den Intervall z.B. auf 100 setzte, muss ich ja zig mal
    auf den Button nächste Frage klicken, bis endlich mal eine von den 4(!) Fragen angezeigt wird...

    richtig, aber wer macht schon quiz nur mit 4 fragen

    übrigens ich habe, wie janzen sagt, getestet und hatte keinen stacküberlauf. vielleicht habe ich mich in meiner behauptung auch getäuscht...



  • Xqgene schrieb:

    es kann einfach vorkommen das random 1000x mal nur 1 oder 2 zurückgibt.

    Sowas kommt nur vor, wenn man randomize() wiederholt aufruft. Da hier der Zufallsgenerator anhand der Systemzeit initialisiert wird (Sekundenbereich) ergeben sich bei quasi unmittelbar hintereinander erfolgendem Aufruf von randomize() identische "Zufallszahlen". Beispiel:

    for (int i = 0; i < 100; i++)
    {
      randomize();
      int rnd = 0;
      rnd = rand() % 10;
      Caption = Caption + ";" + String(rnd);
    }
    


  • @Xqgene: Natürlich wird das Quiz noch mehr Fragen bekommen,is momentan schliesslich nur zum Testen. Ich hab übrigens gedebuggt, und glaube zu wissen wo das Problem ist: Auf eine der Zahlen kommt die Randomize() Funktion nie...
    Das heisst, das dann natürlich irgendwann der Stack überläuft.

    Was mir nur nicht klar ist: Ich sehe den Fehler in der Sytntax nicht. Eigentlich müsste die Randomize() Funktion alle Zahlen durchbekommen...
    selbst mit 1000 Fragen würde ich dann ja irgenwann einen Fehler bekommen...spätestens bei Frage 999.



  • Randomize() kommt sowieso auf keine Zahlen?!?

    -junix



  • @Junix: Wieso???? 😕

    Nachtrag : Ich hab in mein Quiz jetzt 10 Fragen eingebaut,(Codetechnisch habe ich nichts geändert) und bekomme jetzt keinen Stack-überlauf mehr.
    Was für mich unverständlich ist: Ich bekomme höchstens 6 Fragen durch, mehr werden nicht angesprungen. Dabei benutzte ich- Randomize(10)- das heisst 10 verschiedene Zufallswerte..

    Ich raffe es einfach nicht mehr. Entweder ist in meinem obenstehenden Code(ganz oben meine ich) ein Fehler denn ich nicht sehe, oder die Random-Funktion ist einfach nur Mist...



  • Lies in der VCL-Doku mal die 1. Zeile zum Thema Randomize... Dann siehst du dir mal die Funktionsdeklaration an. Und die Beschreibung liest du am Besten auch. Anschliessend klickst du auf "random number routines" unter dem Titel "Category" und schaust dir alle zugehörigen Funktionen (ca. 4) an... Wenn du dann noch nicht weisst wieso, frag nochmals nach.

    -junix



  • Ahja, bitte achte mal auf gross/kleinschreibung. Benutzt du denn nun randomize oder Randomize?

    -junix



  • @Junix: Ich benutze randomize(), also nicht: Randomize()...



  • Hmmm die gibt doch aber auch nix zurück?
    😕
    -junix



  • Der Aufruf erfolgt dann mit int x = random(10)...Das heisst also mit 10 Werten die zufällig generiert werden, oder nicht??



  • Was sagt denn die Funktionsbeschreibung der Hilfe dazu?
    (Wieso weigerst du dich nur krampfhaft die Doku zu rate zu ziehen? (o; )

    -junix



  • Mache ich doch. Aus der Hilfe:

    "random liefert eine Zufallszahl im Bereich von 0 bis (num-1) zurück."

    Mein Problem ist einfach nur das, dass bei random(10), niemals alle Wert zwischen 0 bis 9 einmal generiert werden. Deshalb bekomme ich in meinem Quiz auch nicht alle Fragen durch...(wie gesagt, höchstens 7 von 10 Fragen)

    Eigentlich müssten bei dem Code alle Fragen einmal angesprungen werden:

    void __fastcall TForm1::FormCreate(TObject *Sender)
    {
       // Zählvariable, die dafür sorgen soll, das abgebrochen wird wenn alle
       // Fragen durch sind.
       Zaehler = 0;
       // Das sind die Flags, die verifizieren sollen, ob die Frage schonmal
       // dran war.
       _0,_1,_2,_3,_4,_5,_6,_7,_8,_9 = false;
       randomize();
       Zufall();  
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Zufall()
    {
       int x;
       x = random(10);
    
       switch (x)
       {
          case 0:
             if (Zaehler < 10)
             {
                if (_0 == true)
                   Zufall();
                else                
                { 
                   FrageBox->Caption = "In welches Meer mündet der Amazonas?";
                   Radio1->Caption = " a.) Ins Mittelmeer";
                   Radio2->Caption = " b.) In den atlantischen Ozean";
                   Radio3->Caption = " c.) In den pazifischen Ozean";
                   _0 = true;
                   Zaehler++;
                   _UnChecked;
                   break;
                }
             }
             else
             {
                break;
             }
          case 1:
             if (Zaehler < 10)
             {
                if (_1 == true)
                   Zufall();          
                else                
                { 
                   FrageBox->Caption = "Welcher Berg ist der höchste?";
                   Radio1->Caption = " a.) Matterhorn";
                   Radio2->Caption = " b.) Zugspitze";
                   Radio3->Caption = " c.) Mont Blanc";
                   _1 = true;
                   Zaehler++;
                   _UnChecked;
                   break;
                }
             }
             else
             {
                break;
             }
          case 2:
             if (Zaehler < 10)
             {
                if (_2 == true)
                   Zufall();          
                else                
                { 
                   FrageBox->Caption = "Wie alt ist die Erde?";
                   Radio1->Caption = " a.) c.a. 4 Milliarden Jahre";
                   Radio2->Caption = " b.) c.a. 6 Milliarden Jahre";
                   Radio3->Caption = " c.) c.a. 2 Milliarden Jahre";
                   _2 = true;
                   Zaehler++;
                   _UnChecked;
                   break;
                }
             }
             else
             {
                break;
             }
          case 3:
             if (Zaehler < 10)
             {
                if (_3 == true)
                   Zufall();          
                else                
                { 
                   FrageBox->Caption = "Wo liegt die Wüste Gobi?";
                   Radio1->Caption = " a.) Asien";
                   Radio2->Caption = " b.) Nordamerika";
                   Radio3->Caption = " c.) Afrika";
                   _3 = true;
                   Zaehler++;
                   _UnChecked;
                   break;
                }
             }
             else
             {
                break;
             }
          case 4:
             if (Zaehler < 10)
             {
                if (_4 == true)
                   Zufall();          
                else                
                { 
                   FrageBox->Caption = "Was ist das höchste Gebäude?";
                   Radio1->Caption = " a.) Cheops Pyramide";
                   Radio2->Caption = " b.) Kölner Dom";
                   Radio3->Caption = " c.) Eiffelturm";
                   _4 = true;
                   Zaehler++;
                   _UnChecked;
                   break;
                }
             }
             else
             {
                break;
             }
          case 5:
             if (Zaehler < 10)
             {
                if (_5 == true)
                   Zufall();          
                else                
                { 
                   FrageBox->Caption = "Was ist ein Nachen?";
                   Radio1->Caption = " a.) kleines Boot";
                   Radio2->Caption = " b.) Werkzeug";
                   Radio3->Caption = " c.) Angelzeug";
                   _5 = true;
                   Zaehler++;
                   _UnChecked;
                   break;
                }
             }
             else
             {
                break;
             }
          case 6:
             if (Zaehler < 10)
             {
                if (_6 == true)
                   Zufall();          
                else                
                { 
                   FrageBox->Caption = "Was ist der grösste Fisch";
                   Radio1->Caption = " a.) Riesenhai";
                   Radio2->Caption = " b.) Walhai";
                   Radio3->Caption = " c.) Thunfisch";
                   _6 = true;
                   Zaehler++;
                   _UnChecked;
                   break;
                }
             }
             else
             {
                break;
             }
           case 7:
             if (Zaehler < 10)
             {
                if (_7 == true)
                   Zufall();          
                else                
                { 
                   FrageBox->Caption = "Wie alt bin ich?";
                   Radio1->Caption = " a.) 20";
                   Radio2->Caption = " b.) 16";
                   Radio3->Caption = " c.) 23";
                   _7 = true;
                   Zaehler++;
                   _UnChecked;
                   break;
                }
             }
             else
             {
                break;
             }
           case 8:
             if (Zaehler < 10)
             {
                if (_8 == true)
                   Zufall();          
                else                
                { 
                   FrageBox->Caption = "Wie heisse ich?";
                   Radio1->Caption = " a.) Manfred";
                   Radio2->Caption = " b.) Norbert";
                   Radio3->Caption = " c.) Robert";
                   _8 = true;
                   Zaehler++;
                   _UnChecked;
                   break;
                }
             }
             else
             {
                break;
             }
           case 9:
             if (Zaehler < 10)
             {
                if (_9 == true)
                   Zufall();          
                else                
                { 
                   FrageBox->Caption = "Was ist der höchste Wolkenkratzer?";
                   Radio1->Caption = " a.) Petronas Tower";
                   Radio2->Caption = " b.) Sears Tower";
                   Radio3->Caption = " c.) Messeturm in Frankfurt";
                   _9 = true;
                   Zaehler++;
                   _UnChecked;
                   break;
                }
             }
             else
             {
                break;
             }
       }
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::BtnNextClick(TObject *Sender)
    {
       Zufall();   
    }
    //---------------------------------------------------------------------------
    


  • Das ist eben das, was der Zufall entscheidet... Wer sagt denn, dass alle Zahlen vorkommen müssen?

    Aber das mir nun fast zum 3. Mal in den Augen wehtut, was du da gemacht hast, erlaube ich mri, mal deinen Programmdesign zu kritisieren:
    Er ist gelinde gesagt Schrott. (Mir ist jetzt auch grad aufgefallen wies zum Stackoverflow kommt.)

    Mein vorschlag: Mach einen Struct der in Etwa so aussieht:

    struct TMyQuestion
    {
    AnsiString Frage_AS;
    AnsiString Antworten[3];
    bool beantwortet_bool;
    };
    

    Aus den Fragen machst du nun ein Array von TMyQuestions

    TMyQuestion Fragen_TMQa[10]
    

    und füllst dieses auf:

    Fragen_TMQa[0].Frage_AS = "Frage 1";
    Fragen_TMQa[0].Antworten[0] = "Antwort 1";
    ...
    Fragen_TMQa[0].Antworten[n] = "Antwort n";
    Fragen_TMQa[0].beantwortet_bool = false;
    

    Und siehe da, nun sparst du dir schon den blöden switch-case und du brauchst auch garnicht mehr Zufall() rekursiv (=> zu tiefe Rekursivität führt zu einem Stackoverflow und in deinem Fall ist es genau darum zum stackoverflow gekommen, da zufällig zu oft eine Frage aufgerufen wurde, die bereits dran war) aufzurufen, denn nun kannst du random in einer Shcleife solang aufrufen, is Fragen_TMQa[x].beantwortet_bool false ist.

    Ausserdem bist du plötzlich flexibler mit deinen Fragen, denn selbstverständlich könntest du jetzt die Texte aus einer Datei oder sonst woher laden... (praktisch, ne?)

    Dann noch etwas zum Programmierstil:

    • Gib den Variablen sinnvolle Namen! Wieso zum Geier heisst die Variable die den Fragenindex bestimmt bitte X und nicht FragenIndex? =>Selbstdokumentierende Software
    • Ein Underscore ('_') vor den Bezeichner ist den Compiler und Template-programmieren vorbehalten. Als normalsterblicher Programmierer sollte man von der Verwendung derartiger Bezeichner absehen.
    • Kommentiere deinen Quelltext (Was ist zum Beispiel Unchecked?)
    • Versuche deine Denkensweise etwas umzukrempeln und von Block-Kopier-Programmierung abzusehen
    • Schmeiss globale Variablen über Bord. In den meisten Fällen sind sie unnötig.
    • Versuche möglichst wenige String hart zu codieren. Zur Not mach eine headerfile mit String-Konstanten. das erleichtert dir später das Übersetzen.

    Das ist so das was ich mal auf einen Schlag zumuten will (o: Tschuldige, dass ich hier gliech mit der grossen Kelle zuschlag,aber ich denke du verkraftest das (o;

    -junix



  • Hey, ist doch kein Problem. Danke für deine Mühe. Werde es gleich mal umsetzen...


Anmelden zum Antworten