Nicht-wiederholende Zufallszahlen?

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

 

PacMani

Betreff: Nicht-wiederholende Zufallszahlen?

BeitragSo, März 07, 2010 16:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Mein Problem ist denke ich mal kein neues, ich muss sozusagen "Lottozahlen" erstellen, die sich nicht wiederholen. Allerdings bin ich da leicht unfähig, weil ich bei den Types die Übersicht verloren habe... erstmal der Code!
Code: [AUSKLAPPEN]
Local RandomFlag%
   For i=0 To MaxFlags
      RandomFlag=Rnd(1,BlueFlagID)
      For NBlueFlag = Each TBlueFlag
         If NBlueFlag\ID=RandomFlag Then ShowEntity NBlueFlag\Entity
      Next
   Next

Es gibt da einen Type... der hat ein Entity was standarDmäßig nicht sichtbar ist und eine ID die den Type besser mit einer Zufallszahl auswählen lässt. MaxFlags ist eine Zahl >2, nur nebenbei.

Das obige Beispiel funktioniert, es werden wie gewünscht einige Flaggen sichtbar gemacht, meist genausoviel wie erwünscht (also wie durch MaxFlags festgelegt). Nur gibt es da ein Problem: Einige Flaggen können natürlich mehr als einmal sichtbar gemacht werden, wenn die Zufallszahl zweimal die gleiche ist. Dann währen meist <MaxFlags Flaggen sichtbar...
wie umschiffe ich das Problem am elegantesten, oder besser gesagt, wie überhaupt, wo ich gerade nicht ganz durchblicke?

Xeres

Moderator

BeitragSo, März 07, 2010 16:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Du willst Zufallszahlen ohne Dubletten.
0. Array/Bank in der passenden Größe erstellen
1. Eine Zufallszahl generieren.
2. Zufallszahl mit denen in der Bank vergleichen, wenn schon vorhanden -> 1., wenn noch nicht vorhanden eintragen, counter erhöhen, nächste zahl generieren.
3. Aufpassen, dass du keine endlos schleife baust.
Danach enthält Array/Bank Zufällige Zahlen bei denen keine Doppelt vorkommt.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

ToeB

BeitragSo, März 07, 2010 16:48
Antworten mit Zitat
Benutzer-Profile anzeigen
ICh glaub das ist etwas schwer zu verstehen. Ich erklärs hier einfacher Wink

Also, man will jetzt zum Beispiel 6 Zahlen auf 49 ziehen. Dafür macvht man folgendes :
Code: [AUSKLAPPEN]
Dim zahl(5)
For i = 0 to 5
Zahl(i) = Rand(1,49)
next


Soweit so gut, aber jetzt möchte man ja die ausschließen die schon gezogen worden sind. Dazu fängt man eine while schleife an.
Code: [AUSKLAPPEN]
Dim zahl(5)
SeedRnd MilliSecs()
For i = 0 To 5
   schonbenutz = 1 ;Hier geht man davn aus, das die zahl schon benutz worden ist
   While schonbenutz = 1
      zahl(i) = Rand(1,49)
      schonbenutz = 0
      For j = 0 To 5
         If i <> j Then
            If zahl(i) = zahl(j) Then schonbenutz = 1 : Exit
         EndIf
      Next
   Wend
   Print zahl(i)
Next
WaitKey()
End


So habs mal eben gemacht...Ist ganz einfach und selbstklärend ...


mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!
 

PacMani

BeitragSo, März 07, 2010 16:51
Antworten mit Zitat
Benutzer-Profile anzeigen
EDIT: Mein zwischenzeitlicher Code war totaler Müll... hier noch mal was ich mir so dachte:
Code: [AUSKLAPPEN]
   Local RandomNumbers%(MaxFlags)
   Local CurrentNumber%
   Local RandomNumber% = Rnd(1,BlueFlagID)
   For i=0 To MaxFlags
      If RandomNumbers(i)=RandomNumber Then
         
      Else
         RandomNumbers(CurrentNumber)=RandomNumber
         CurrentNumber=CurrentNumber+1
      End If
   Next

Autsch!


PS: Thx, ToeB! Musste den Code erstmal zeilenweise bedenken, bis ich ihn dann verstanden habe, aber ist in der Tat natürlich voll funktionsfähig Wink

hazumu-kun

BeitragMo, März 08, 2010 0:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn man die laufzeit des Algorithmus konstant halten will (es kann durchaus passieren das die prüfung sehr oft hintereinander ne neue zahl generieren muss) erstellt man ein Speicherfeld mit allen möglichen zahlen, und rührt es durch:

BlitzBasic: [AUSKLAPPEN]

Dim zahl(48)
For i= 0 To 48
zahl(i)=i
Next

;Ordentlich durchrühren
SeedRnd MilliSecs()
For i= 1 To 49*49
;Zufällig zwei Zahlen wählen
pos1= Rand(0,48)
pos2= Rand(0,48)

;Zahlen vertauschen
tmp= zahl(pos1)
zahl(pos1)= zahl(pos2)
zahl(pos2)= tmp
Next


Weiß aber nichtmehr genau wie oft man mindestens tauschen muss um die Reihenfolgen sicher zu zerstören. Ich denke es war arraygröße^2 mal.
Warum kann es keine omnipotente Macht geben?
Weil diese omnipotente Macht in der Lage sein müsste, einen so schweren Stein zu schaffen, dass sie ihn nicht heben kann
-> nicht omnipotent

Midimaster

BeitragMo, März 08, 2010 10:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Ein Zufallsgenerator, der jede Zahl garantiert nur 1x bringt, sollte aus einer TYPE-Liste erstellt werden. Jedesmal, wenn eine Zahl gezogen wurde wird einfach das Element gelöscht:

Im Testprogramm wird zunächst eine Typ-Liste mit den 10 Zufallszahlen erstellt. Dann in einer Repeat-Schleife alle in zufälliger Reihenfolge gezogen.
Test-Programm:BlitzBasic: [AUSKLAPPEN]
Graphics 320,200
Type ZufallTyp
Field Wert%
End Type

For i%=1 To 10
Neu.ZufallTyp = New ZufallTyp
Neu\Wert = i
Next
Global Max%=i-1
SeedRnd

Repeat
Print ZufallsZahl()
Until Max=0
Zufallsfunktion:BlitzBasic: [AUSKLAPPEN]
Function ZufallsZahl%()
Local Ergebnis%, i%, Zufall%
Zufall% = Rand(1,Max)
Max = Max-1
For Neu.ZufallTyp = Each ZufallTyp
i = i+1
If I=Zufall Then
Ergebnis=Neu\Wert
Delete Neu
Return Ergebnis
EndIf
Next
End Function

Diese Function zieht immer eine aus max% vorgegebenen Zahlen. Wird die Zahl gezogen, wird sie auch gleich aus der Liste entfernt.


Mit der Funktion wäre es auch möglich, "nicht fortlaufende" Zahlen, Strings oder Entitys zu ziehen:

BlitzBasic: [AUSKLAPPEN]
Graphics 320,200
Type ZufallTyp
Field Wert$
End Type

Neu.ZufallTyp = New ZufallTyp
Neu\Wert = "Tarzan"
Neu.ZufallTyp = New ZufallTyp
Neu\Wert = "Jane"
Neu.ZufallTyp = New ZufallTyp
Neu\Wert = "Judy"
Neu.ZufallTyp = New ZufallTyp
Neu\Wert = "Clarence"

Global Max%=4
SeedRnd

Repeat
Print ZufallsZahl()
Until Max=0



Function ZufallsZahl$()
Local Ergebnis$, i%, Zufall%
Zufall% = Rand(1,Max)
Max = Max-1
For Neu.ZufallTyp = Each ZufallTyp
i = i+1
If I=Zufall Then
Ergebnis=Neu\Wert
Delete Neu
Return Ergebnis
EndIf
Next
End Function

ToeB

BeitragMo, März 08, 2010 14:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Sry midmaster, das du dir vileicht ein wenig arbeit damit gemacht hast ect. aber ich glaub das bringt ihm nix. Er will ja nur 6 zahlen zwischen 1 und 49 ziehen, da bringt es nix und wird auch viel zu unübersichtlich wenn er alles 49 zaheln in Types speichern würde. Also, Muss man nur ein array mit 6 feldern haben, eine zahl auswählen, dann prüfen ob es in den anderen 5 feldern diese zahl schon gibt, wenn ja, eine neue zahl prüfen, wenn nein diese zahl in das array speichern. So wie ichs oben gemacht habe. Da machn types sowas von keinen sinn, weil man kann auch mit arrays genau EINE zahl von 1 bis max raususchen... und das mit einem code der um die hälfte kleiner ist und sogar noch viel übersichtliger ist. Ich wollte dich jetzt hier nicht fertig machen oder so, ich wollte nur allen mitteilen das es in diesem Bereich eine falsche lösung ist (in anderen Bereichen bei vielen zahlen machts sinn, da geb ich dir recht, aber bei nur 6 aus 49 ? nee Wink )

mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!

Midimaster

BeitragMo, März 08, 2010 20:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Oh, das hatte ich ganz anders verstanden... Er schrieb " sozusagen Lottozahlen" und dann noch was von "Flaggen". Da dachte ich mir, ein universeller Algo wäre was für ihn.

Und in seinem eigenen Code scheint die Menge der Zufallszahlen sowie die Anzahl der Ziehungen variabel zu sein...Mal sehen, was er selbst spricht....

Und..."fertigmachen" ist sicher das Letzte an das ich denke, wenn mir jemand was Kritisches schreibt. Mach dir da mal keine Sorgen...Sowas würde ich nie vermuten. Außerdem bin ich nicht aus Zuckerguss. Wink

Kritik seh ich immer dialektisch und nehm sie nie persönlich!
 

Krischan

BeitragMo, März 08, 2010 20:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich bin auch ein Fan vom Vertauschen: ein Array wird mit den Zahlen 1...49 gefüllt und dann kurz vermischt. Dann muss man nur noch das Array ausgeben und bekommt so jede Zahl nur 1x:

Code: [AUSKLAPPEN]
.start

Cls
Locate 0,0

Dim Array(0)

SeedRnd MilliSecs()

CreateRandomArray(49)

For i=1 To 6
   
   Print "Lottonummer: "+Array(i)
   
Next

Print "Zusatzzahl : "+Array(i+1)

WaitKey

If KeyHit(1) Then End

Goto start

End

Function CreateRandomArray(size%)
   
   Local i%,n%,m%,z%
   
   ; Array neu dimensionieren
   Dim Array(size)
   
   ; Array mit allen Zahlen von 1...size füllen
   For i=1 To size-1 : Array(i)=i : Next
   
   ; Würfeln
   For n=1 To size-2
      
      m=Rand(n,size-1)
      z=Array(n)
      
      Array(n)=Array(m)
      Array(m)=z
      
   Next
   
End Function
 

PacMani

BeitragMo, März 08, 2010 22:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich danke erstmal jedem für die vielen Ideen an denen ich mich wohl auch noch bei weiteren Zufallszahlen orientieren werde. Mein Code sieht nun übrigens so aus, daraus kann man schließen was ich gesucht hab Wink
Code: [AUSKLAPPEN]
Dim SelectedFlags(0)
Function CreateFlagSelection(AvailableFlags)
   Dim SelectedFlags(MaxFlags-1)
   Local Used%
   For i=0 To MaxFlags-1
      Used=True
      While Used=True
         SelectedFlags(i)=Rnd(1,AvailableFlags)
         Used=False
         For j=0 To MaxFlags-1
            If i<>j Then
               If SelectedFlags(i)=SelectedFlags(j) Then Used=True : Exit
            End If
         Next
      Wend
   Next
End Function

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group