lafilia100: Zufallszahl ohne Dopplung erzeugen

Hey,

ich habe ein kleines Problem mit einem von mir geschrieben Script.

Das Script generiert aus einem Array in zufälliger Reihenfolge Fragen bzw. die HTML-Elemente dazu.

Den Wertebereich der Zahlen habe ich eingeschränkt, sodass er von null bis zu meiner Anzahl an Fragen, die generiert werden sollen (-1) reicht.

Das funktioniert auch soweit. Was leider nicht funktioniert, ist eine Vermeidung der Dopplung der Zahlen.

Sprich, es werden Fragen doppelt genommen, weil für die Generierung mit identischen Indizes gearbeitet wird.

Mein Lösungsversuch:

Ich erzeuge ein Array "benutzteIndizes" und prüfe bei jeder Zufallszahlgenerierung, ob die Zahl, die generiert wurde, bereits in dem Array enthalten ist. Wenn das der Fall ist, soll weiter generiert werden, bis eine Zahl gefunden wurde, die noch nicht im Array enthalten ist...

Soweit die Theorie... leider funktioniert es nicht.
Ich wäre so froh, wenn mir jemand helfen könnte und es endlich funktionieren würde:

var benutzteIndizes = new Array();

``

function erstelleQuiz(){ //erstellt zunächst zwei Arrays mit den Fragen und
                             //zugehörigen Antworten. Anschließend werden die Inhalte
                             //in neu erstellte HTML-Elemente eingefügt und in die
                             //Knotenstruktur eingebunden.

for (var i = 0; i < Fragen.length; i++) {////Code zur HTML-Generierung

var neuerIndex = erzeugeZufallsZahl();
        benutzteIndizes[i] = neuerIndex;

for (var Antworten in Fragen[neuerIndex]){

//Code zur HTML-Generierung

}

}
}
function erzeugeZufallsZahl(){

var erzeugt = false;
while(erzeugt == false){
    var a =  (Math.ceil(Math.random()*((Fragen.length)-1)));
if(istInArray(a, benutzteIndizes)==false){erzeugt = true}
}

return a;
}
function istInArray(zahl, array){
 for (i=0;i<array.length;i++){
  if ((array[i] == zahl)==true){
  return true;}
  else{return false;}
}}

Hab schon endlos damit rumgespielt, aber es will und will nicht...
Vielen Dank für eure Hilfe!

  1. hallo

    function istInArray(zahl, array){
    for (i=0;i<array.length;i++){
      if ((array[i] == zahl)==true){
      return true;}
      else{return false;}
    }}

    ich würde die Funktion so gestalten, dass sie innerhalb der Schleife nur true zurückgeben kann.
    Ist zahl also im Array, wird bei array[i]==zahl --> true zurückgegeben. Damit wäre die Funktion ja beendet. Ist zahl nicht im Array, läuft die Schleife ergebnislos ab. Nach der Schleife wird dann false zurückgegeben.

    --
    "Sir! We are surrounded!" - "Excellent! We can attack in any direction!"
  2. Hallo,

    Das Script generiert aus einem Array in zufälliger Reihenfolge Fragen bzw. die HTML-Elemente dazu.

    Das funktioniert auch soweit. Was leider nicht funktioniert, ist eine Vermeidung der Dopplung der Zahlen.

    Mische das Array. Siehe z.B. Jürgens Vorschlag.

    Freundliche Grüße

    Vinzenz

    1. Hallo,

      Mische das Array. Siehe z.B. Jürgens Vorschlag.

      Hallo,

      Du meinst folgenden?

      Array.prototype.shuffle=function() {  
       var l=this.length,t,zi,i=l;  
        do {  
         zi=Math.floor(Math.random()*i);  
         t=this[zi];  
         this[zi]=this[--i];  
         this[i]=t;  
        } while (i);  
      }  
      
      

      Das Ding mischt doch nicht. i wird anfangs mit 1 initialisiert und im ersten Durchlauf mit --i zu 0, so dass wegen while(i) es keinen zweiten Durchlauf geben kann, oder sehe ich das falsch?

      Gemeint ist wahrscheinlich etwas wie die Methode nach Fischer-Yates, aber die geht so:

      myArray.shuffle = function(){  
        
        var v,j,i=this.length;  
        if(!i){return false;}  
        
        while(--i){  
        
          v=this[i];  
          j=Math.floor(Math.random()*(i+1));  
          this[i]=this[j];  
          this[j]=v;  
        }  
      }  
      
      

      Das ist verteilungsmäßig so gut wie der Zufallsgenerator halt ist.

      Es wird Element aus dem Array zufällig gezogen und mit dem letzten Element vertauscht, dann das nächste Element aus den verbleibenden (length-1) gezogen und mit dem vorletzen vertauscht usw., bis das ganze Array durchgemischt ist.

      Gruß, Don P

      1. Hallo,

        Sehe gerade, dass wohl nicht i=1 (eins) gemeint ist, sondern ein kleines L, was mit this.length anfangs die Länge des Arrays ist. Dann könnte es auch klappen mit Jürgens Vorschlag.

        Gruß, Don P

        1. Hallo Don,

          ... Dann könnte es auch klappen mit Jürgens Vorschlag.

          glaub mir, es klappt.

          Gruß, Jürgen

          1. Hallo,

            Hallo Don,

            ... Dann könnte es auch klappen mit Jürgens Vorschlag.

            glaub mir, es klappt.

            Ich glaub's dir. Deine Funktion ist besser als meine. Habe sie jetzt übernommen, danke dir.

            Gruß, Don P

            1. Hallo Don,

              ... danke dir.

              ich reiche den Dank an das Forum weiter, in dessen Umfeld und mit dessen Hilfe der Mischer entstanden ist.

              Gruß, Jürgen

  3. Alternative:

    Fragenarray -> zufällig eine Frage (eine Arrayelement) auswählen -> dieses Arrayelement nutzen und dann aus dem Array löschen -> nächster Durchlauf

    Dopplungen werden garantiert vermieden und die lahme Suchschleife fällt weg (die kann am Ende recht lange suchen bis sie endlich den letzten freien Index findet)

    1. Hallo,

      Fragenarray -> zufällig eine Frage (eine Arrayelement) auswählen -> dieses Arrayelement nutzen und dann aus dem Array löschen -> nächster Durchlauf

      Es ist nicht ganz einfach ein Array-Element wirklich zu löschen. Dazu muss man das Array an der Stelle jeweils auseinandernehmen (splice), mit shift oder pop das Element entfernen und das Array dann wieder zusammensetzen, was ziemlich umständlich wird.

      Ansonsten kann man ein Element nicht löschen, sondern ihm nur den Wert undefined zuweisen.

      Da finde ich das Mischen besser, wie oben vorgeschlagen.

      Gruß, Don P

      1. Es ist nicht ganz einfach ...

        aber so schwierig nun auch wieder nicht

        extrahiere Element i:

        new_array=altarray.slice(0,i).concat(altarray.slice(i+1));

      2. [latex]Mae  govannen![/latex]

        Es ist nicht ganz einfach ein Array-Element wirklich zu löschen. Dazu muss man das Array an der Stelle jeweils auseinandernehmen (splice), mit shift oder pop das Element entfernen und das Array dann wieder zusammensetzen, was ziemlich umständlich wird.

        Nö.

        var arr = [40,41,42,43,44,45,46,47];  
          
        alert(arr.length) // 8  
          
        var removeIx = 4; // 4.Eintrag entfernen  
          
        arr.splice(removeIx - 1, 1);  
          
        alert(arr); // 40,41,42,44,45,46,47  
        alert(arr.length); // 7
        

        Cü,

        Kai

        --
        Hard to believe that anyone would use Prototype.js at this
        point. It was a bad idea in 2006 and it hasn't gotten any better with age. (David Mark)
        Foren-Stylesheet Site Selfzeugs
        SelfCode: sh:( fo:| ch:? rl:( br:< n4:( ie:{ mo:| va:) js:| de:> zu:) fl:( ss:| ls:?
        1. danke, so hatte ich die Beschreibung in SelfHTML noch nicht verstanden

          1. Hallo,

            danke, so hatte ich die Beschreibung in SelfHTML noch nicht verstanden

            Jetzt, wo ich es gesehen habe, kommt es mir doch irgendwie bekannt vor. Ist anscheinend doch einfacher, als ich dachte, aber trotzdem nicht sonderlich performant.

            Gruß, Don P

            --
            sh:( fo:) ch:? rl:( br:] n4:~ ie:% mo:? va:{ js:) de:/ zu:] fl:( ss:| ls:&
            1. ... aber trotzdem nicht sonderlich performant.

              kannst du diese Behauptung irgendwie belegen?

              1. Hallo,

                ... aber trotzdem nicht sonderlich performant.

                kannst du diese Behauptung irgendwie belegen?

                Nicht direkt, man müsste es mal messen. Aber es würde doch mich sehr wundern, wenn wiederholtes splicen nicht deutlich langsamer wäre, als nur Inhalte der Array-Elemente zu ändern wie bei der Mischmethode. Da würde ich jede Wette eingehen. Habe allerdings auch schon Wetten verloren... ;-)

                Gruß, Don P