PDA

Vollständige Version anzeigen : Zufällige Verteilung - RND-Funktion


OlliU
26.04.2001, 15:48
Hallo, Accessler!

Folgende Aufgabe: Ich habe 30 Fragen, die nach einem Zufallsprinzip auf die Positionen 1-30 verteilt werden sollen.

Hierzu habe ich 2 Probleme:
1. Ich erhalte bei einer Zufallsfunktion immer denselben Wert... irgendwas läuft falsch

2. Wenn ich die erste Frage verteilt habe, kann ich sie auf Position 1 setzen. Dann bleiben noch 29 übrig. Wie erreiche ich, dass beim zweiten Durchlauf nur noch aus den verbleibenden 29 gesucht wird, dann nur noch aus den 28 übrigen, dann den 27, usw...

Für jede Antwort dankbar

Viele Grüsse

OlliU

Pittchen
26.04.2001, 15:56
Hey, OlliU:

zu deiner ersten Frage: Du mußt mit Randomize den Zufallsgenerator initialisieren;
die 2. Frage ist etwas komplexer. Ich denke mal darüber nach

Gruß Pittchen

Stefan Kulpa
26.04.2001, 16:16
Hallo OlliU,

die folgende Lösung nutzt das Dictionary-Object des Scripting-Objekts.
Dazu musst du einen Verweis auf die Datei SCRRUN.DLL im Systemverzeichnis erstellen. Es gibt sicher noch weitere Lösungen, aber diese viel mir spontan ein:

<FONT SIZE=1 FACE=Courier New><FONT COLOR=#000080>Public</FONT> <FONT COLOR=#000080>Sub</FONT> Test()

<FONT COLOR=#000080>Dim</FONT> lCounter <FONT COLOR=#000080>As</FONT> <FONT COLOR=#000080>Long</FONT>
<FONT COLOR=#000080>Dim</FONT> objDict <FONT COLOR=#000080>As</FONT> <FONT COLOR=#000080>New</FONT> Scripting.Dictionary

<FONT COLOR=#008000>'// In einem Dictionary 30 einträge generieren</FONT>
<FONT COLOR=#000080>For</FONT> lCounter = 1 <FONT COLOR=#000080>To</FONT> 30
objDict.Add <FONT COLOR=#000080>CStr</FONT>(lCounter), "Frage " & lCounter <FONT COLOR=#008000>'oder die Frage direkt ;-)</FONT>
<FONT COLOR=#000080>Next</FONT>

<FONT COLOR=#000080>Do</FONT>
Randomize
lCounter = Int((30 * Rnd) + 1)
<FONT COLOR=#000080>If</FONT> objDict.Exists(<FONT COLOR=#000080>CStr</FONT>(lCounter)) <FONT COLOR=#000080>Then</FONT>
Debug.<FONT COLOR=#000080>Print</FONT> objDict.Item(<FONT COLOR=#000080>CStr</FONT>(lCounter)) <FONT COLOR=#008000>'Frage stellen ...</FONT>
objDict.Remove (<FONT COLOR=#000080>CStr</FONT>(lCounter))
<FONT COLOR=#000080>End</FONT> <FONT COLOR=#000080>If</FONT>
<FONT COLOR=#000080>Loop</FONT> <FONT COLOR=#000080>Until</FONT> objDict.Count = 0

<FONT COLOR=#000080>End</FONT> <FONT COLOR=#000080>Sub</FONT>

</FONT>

In der Debug.Print Zeile wird die entsprechende Frage gestellt. Die Frage selbst könntest du in der For-Schleife als Bestandteil des Dictionary-Objekts einfügen.

HTH,

Scorefun
26.04.2001, 16:30
Ho Olli,

hab mal was gebastelt:

Folgende Funktion ermittelt Dir eine Zufallszahl:

Function aekZufallszahlAusgeben(Untergrenze, Obergrenze)

Randomize Timer
aekZufallszahlAusgeben = Int((Obergrenze - Untergrenze + 1) _
* Rnd + Untergrenze)

End Function

Die habe ich von www.fullaccess.de (http://www.fullaccess.de)

Und folgende (von mir gestrickte) Routine
verteilt Dir Deine 30 Fragen

Annahme:
Die Tabelle heißt : tblFragen
Das Feld, in der die Zufallszahlen reinsollen heißt FragePosition

Function FragenZuordnen()
Dim r As Recordset, i As Long, x As Long

On Error GoTo Err_Fragen

For i = 1 To 30
'Recordset aktualisieren
Set r = CurrentDb.OpenRecordset("select * from tblFragen where fragePosition = Null")
'Zufallszahl ermitteln
x = aekZufallszahlAusgeben(i, 30)
'Setze Datensatzzeiger auf Zufallszahl
r.Move x
r.Edit
r!fragePosition = i
r.Update
Next i

Exit Function

Err_Fragen:
'Wenn nicht zum Datensatz gesprungen werden kann
If Err = 3021 Then
'gehe zum Anfang zurück
r.MoveFirst
'und versuche es nochmal
Resume
End If
End Function

Versuch's mal

OlliU
27.04.2001, 20:47
Hallo, Pittchen, Stefan und Scorefun!

Erst mal vielen Dank an Euch!
Endlich erhalte ich mal eine andere Zahl und nicht immer nur dieselbe (wurde langsam langweilig) http://www.microsyskramer.de/ubb/smile.gif

Aber zu den beiden Routinen von Stefan und Scorefun:
Werden denn nicht nach wie vor Zufallszahlen aus allen 30 möglichen generiert?
(und nicht nur aus den verbleibenden?)

Oder habe ich da was überlesen?

Viele Grüße

OlliU

Stefan Kulpa
28.04.2001, 05:42
Hallo OlliU,

was mein Beispiel betrifft:

In jedem Schleifendurchlauf wird eine Zufallszahl zwischen 1 und 30 erzeugt. Allerdings werden bereits angezeigte "Fragen" aus dem "Dictionary" sofort gelöscht, um nicht nochmal angezeigt zu werden. Dadurch wird die Anzahl Schleifendurchläufe erhöht, da ja mit jedem Durchlauf weniger "Treffer" erzeugt werden.

Zum Test kannst Du Dir die aktuell erzeugte Zufallszahl anzeigen lassen; setze dazu direkt unter die Zeile
lCounter = Int((30 * Rnd) + 1)
den Ausgabebefehl
Debug.Print lCounter
um nachvollziehen zu können, wie die Zahlen generiert werden.
Damit ist die Aufgabe:
"Wie erreiche ich, dass beim zweiten Durchlauf nur noch aus den verbleibenden 29 gesucht wird, dann nur noch aus den 28 übrigen, dann den 27, usw..." erfüllt, da tatsächlich nur noch in den jeweils restlichen Einträgen gesucht wird ...

Gruß,

Scorefun
28.04.2001, 11:00
Bei mir dient die Zufallszahl (x) lediglich dazu, innerhalb des Recordsets zu einem zufälligen Datensatz zu springen und den Zaehler (i) einer Frage zuzuordnen.

Bei jedem Schleifendurchlauf enthält das Recordset dann nur noch die Fragen, die noch keine Nummer (i) haben.

Aber der Code von Stefan ist meiner "Krücke" mit Sicherheit vorzuziehen.