Zufallszahl ohne Dopplung erzeugen
lafilia100
- javascript
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!
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.
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
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
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
Hallo Don,
... Dann könnte es auch klappen mit Jürgens Vorschlag.
glaub mir, es klappt.
Gruß, Jürgen
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
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
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)
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
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));
[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
danke, so hatte ich die Beschreibung in SelfHTML noch nicht verstanden
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
... aber trotzdem nicht sonderlich performant.
kannst du diese Behauptung irgendwie belegen?
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