Neuling fragt.......: Zufallszahlen generieren, ohne eine doppelt zu erhalten

  • Hallo an alle......

    Ich bin ein Frischling, was AutoIt angeht. Deswegen möchte ich mir einige Scripte basteln, einfach um zu lernen.

    Die neueste Einbildung von mir: Ich möchte ein Script erstellen, in dem aus einem Zahlenbereich mehrere Zufallszahlen generiert werden, ohne das eine Zahl doppelt erscheint. Wäre nett, wenn ihr mir einige Denkanstöße verpasst, am besten mit ner Erklärung für Dummies dazu.

    Danke

    L.A.

    • Offizieller Beitrag

    Diese Frage wurde schon einige Male beantwortet. Suche am besten mal nach: Lottozahlen.

    Hier ein recht kurzes Skript, was Deine Bedingungen erfüllt:

    Spoiler anzeigen
    [autoit]


    Global $p, $s, $a[50] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
    For $i = 49 To 43 Step -1
    $p = Random(1, $i, 1)
    $s &= $a[$p] & ' '
    $a[$p] = $a[$i]
    Next
    MsgBox(0,'',$s)

    [/autoit]
  • Dickes Danke, das lege ich mir zur Seite, vielleicht brauche ich irgendwann mal :D

    Hab mich nicht genau ausgedrückt, stelle ich fest.Ich dachte eher so in die Richtung, das man mehrere Objekte in verschieden Ziele platziert. Bsp: Ich habe 5 Kugeln und 6 Löcher. Ich möchte die 5 Kugeln zufällig auf die Löcher verteilen, so das immer nur eine Kugel pro Loch liegt. Das Ganze eben erst mal nur mit Zahlen, sonst wirds zuviel für mich. ( bin auch schon etwas älter, da gehts nicht mehr so schnell).....

  • Hier ein andere Variante:

    [autoit]


    #include <Array.au3>
    Dim $aArray[6] = [1, 2, 3, 4, 5, 6]
    $aNewArray = _ArrayPermute($aArray, ",") ;permutiere Array
    MsgBox(0, "Zufall", "Löcher Reihenfolge: " & StringTrimRight($aNewArray[Random(1, $aNewArray[0], 1)], 2))

    [/autoit]

    Idee: es werden alle Möglichkeiten (Permutation) der 6 Zahlen in ein Array abgelegt und anschließend per Zufall ausgesucht.

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    Einmal editiert, zuletzt von UEZ (24. Mai 2011 um 23:46)

  • Nochmal ein Dickes Danke, ich werde mich nach dem Schlafen mal damit befassen und meine Fragen stellen. Schließlich möchte ich ja ein Script nicht nur haben, sondern auch verstehen.....

  • Guten Morgen,

    ich bleibe mal bei meinem Beispiel mit Kugeln und Löchern.

    Wenn ich den Code von UEZ einigermaßen verstehe, werden mit der 2.Zeile die Anzahl der Löcher festgelegt? Dort könnte ich also beliebig viele angeben.....

    was ich noch nicht verstehe:

    1. Wieso gibt mir die MsgBox die gewünschten Anzahl der Löcher-1?
    2. Wie müßte ich das Script ändern, wenn die Anzahl der Löcher gleich bleibt, aber die Anzahl der Kugeln geändert wir?
    3. Was müßte ich tun, um z.B. $Kugel1 ihr Loch zuzuweisen, um später mit dem Wert arbeiten zu können?

    Ich bitte auch darum, nicht nur ein Script zu schreiben und zu posten, sondern auch für Dummies zu erklären. Ich möchte ja verstehen, was da steht........

  • Zitat

    Wenn ich den Code von UEZ einigermaßen verstehe, werden mit der 2.Zeile die Anzahl der Löcher festgelegt?


    Ja. Für 7 Stück sähe das so aus: $Array[7] = [1, 2, 3, 4, 5, 6, 7]

    Zitat

    1. Wieso gibt mir die MsgBox die gewünschten Anzahl der Löcher-1?


    Das liegt an StringTrimRight. Die Funktion entfernt das letzte Ergebnis von ArrayPermute, da du ja 5 Kugeln auf 6 Löcher verteilen wolltest. ;)

    Zitat

    2. Wie müßte ich das Script ändern, wenn die Anzahl der Löcher gleich bleibt, aber die Anzahl der Kugeln geändert wir?


    StringTrimRight anpassen, so dass die gewünschte Anzahl an Ergebnissen + Trennzeichen abgeschnitten wird.

    Zitat

    3. Was müßte ich tun, um z.B. $Kugel1 ihr Loch zuzuweisen, um später mit dem Wert arbeiten zu können?


    Den String in ein Array aufteilen (StringSplit) und dann mit _arraySearch den Index bzw. das "Loch" des entsprechenden Elements finden.

  • Der Nachteil der _ArrayPermute() Methode ist, wenn du ein größers Array nimmst, welches dann n! + 1 Arrayspeicher frisst.

    Besser wäre ein Mischen des Arrays.

    Wie? Z.B so:

    Spoiler anzeigen
    [autoit]


    #include-once
    ; #FUNCTION# ======================================================================================
    ; Name ................: Shuffle_Array()
    ; Version .............: v0.50 build 2011-05-24 beta
    ; Description .......: Shuffles an array - support 1D and 2D arrays only
    ; Syntax ..............: Shuffle_Array(ByRef $array, $startindex = 0, $endindex = 0)
    ; Parameters ........: $array - the array to shuffle
    ; $startindex = from which index to start the shuffling
    ; $endindex = to which index to start the shuffling; 0 means last index of the array
    ; Return values ....: True
    ; Failure 1 - $array is not an array
    ; Failure 2 - array has more than 2 dimensions
    ; Failure 3 - array is empty
    ; Failure 4 - $startindex / $endindex are set wrongly
    ; Author ..............: UEZ
    ; Modified ............:
    ; Remarks ............:
    ; Related ..............: Array
    ; =================================================================================================
    Func Shuffle_Array(ByRef $array, $startindex = 0, $endindex = 0)
    If Not IsArray($array) Then Return SetError(1, 0, 0)
    If UBound($array, 0) > 2 Then Return SetError(2, 0, 0)
    If UBound($array) = 1 Then Return SetError(3, 0, 0)
    Local $u1
    If Not $endindex Then
    $u1 = UBound($array) - 1
    Else
    If $endindex > $startindex And $endindex < UBound($array) Then
    $u1 = $endindex
    Else
    Return SetError(4, 0, 0)
    EndIf
    EndIf
    If UBound($array, 2) Then
    Local $aSwap[1][UBound($array, 2)], $u2 = UBound($array, 2) - 1
    Local $i, $j, $r
    For $i = $startindex To $u1
    $r = Random($startindex, $u1, 1)
    For $j = 0 To $u2
    $aSwap[0][$j] = $array[$i][$j]
    $array[$i][$j] = $array[$r][$j]
    $array[$r][$j] = $aSwap[0][$j]
    Next
    Next
    Else
    Local $aSwap[1]
    For $i = $startindex To $u1
    $r = Random($startindex, $u1, 1)
    $aSwap[0] = $array[$i]
    $array[$i] = $array[$r]
    $array[$r] = $aSwap[0]
    Next
    EndIf
    Return 1
    EndFunc

    [/autoit]

    Du mischst das Array und nimmst die Reihenfolge der Zahlen Lochnummer.

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    2 Mal editiert, zuletzt von UEZ (24. Mai 2011 um 22:03)

  • Ich hab mir auch mal Gedanken gemacht und das ist dabei herausgekommen
    Ich hoffe mal mir ist kein Fehler unterlaufen und das Script macht das was es soll...

    Spoiler anzeigen
    [autoit]


    #Include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $max = 500
    Global $arr [$max + 1]
    For $y = 1 To $max
    $random = Random(1,$max,1)
    For $x = 1 To UBound($arr)-1
    If $arr [$x] = $random Then
    $y -= 1
    $random = ""
    ExitLoop
    EndIf
    Next
    If $random <> "" Then $arr [$y] = $random
    Next

    [/autoit] [autoit][/autoit] [autoit]

    _ArrayDisplay($arr) ; Zufällige Reihenfolge
    _ArraySort($arr) ;Ordnen des Arrays
    _ArrayDisplay($arr) ; Sortierte Reihenfolge

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit]

    Ich als Anfänger versuch mich immer wieder an Problemen anderer Anfänger^^

  • Würde das so lösen...

    [autoit]


    #include <array.au3>

    [/autoit][autoit][/autoit][autoit]

    $kugeln = 5
    $loecher = 12

    [/autoit][autoit][/autoit][autoit]

    Dim $aErgebnis[$kugeln+1] ; Array das für jede Kugel ein Loch speichert, das Array ist 1 größer als die Kugelzahl, damit wir nich mit Index 0 anfangen, dadurch hat Kugel 1 Index 1 usw.

    [/autoit][autoit][/autoit][autoit]

    For $i=1 to $kugeln ; Hier wird nun jeder Kugel ein Loch zugwiesen
    While 1
    $zufallsLoch = Random(1,$loecher,1) ; wählt ein zufälliges Loch
    if _ArraySearch($aErgebnis,$zufallsLoch) = -1 Then ; wenn das zufällige Loch noch nicht vergeben wurde
    $aErgebnis[$i]=$zufallsLoch ; Loch für die aktuelle Kugel speichern
    ExitLoop ; while Schleife verlassen, also mit der nächsten Kugel weitermachen
    EndIf
    WEnd
    Next

    [/autoit][autoit][/autoit][autoit]

    _ArrayDisplay($aErgebnis)

    [/autoit][autoit][/autoit][autoit]

    $antwort = InputBox("Quiz","Wo ist Kugel 1?")
    if $aErgebnis[1] = $antwort Then
    MsgBox(0,"Richtig!","Kugel 1 war in Loch " & $aErgebnis[1])
    Else
    MsgBox(0,"Falsch!","Kugel 1 war in Loch " & $aErgebnis[1])
    EndIf

    [/autoit]
  • Danke, Danke, Danke......

    ich glaub, ich bin innerlich doch blond.....Ich werd mal versuchen, aus dem Ganzen schlau zu werden, ein wenig rumbasteln und hoffen, das ich das Alles irgendwie verstehe.........


    Und wenn ein Moderator den Thread in " Neuling LewAlton braucht Hilfe...." oder so umbenennt, hab ich meinen eigenen Thread und brauch beim nächsten Problem keinen neuen eröffnen.....


    Dazu noch ein Lob an euch, weil ihr nicht nur Scripte und Fachwissen hergebt, sondern auch versucht, in "normalen" Deutsch zu erklären..........

  • Für Zufallselemente aus einem gegebenen, begrenzten Universum, soll heißen, du weißt, wie viele du aus wie vielen haben willst, wäre mein erster Ansatz immer ein Array.

    Aber zu deinem Hinweis in deinem letzten Beitrag:
    Erstens kannst du das Thema in deinem ersten Beitrag hier ganz oben selber umbenennen ;)
    Zweitens solltest du das nicht tun, sondern bei einem anderen Problem erneut suchen und gegebenenfalls ein neues Thema eröfnen, damit andere, die dasselbe Problem haben, dein Thema zu diesem Problem finden können.

  • Ich glaub, ich habs verstanden, zumindest zum Großteil.........

    Danke nochmal und bis zum nächsten Problem :D :D