Den Zufall in den Griff bekommen
Lingo-Basics:
random(100) erzeugt eine Zufallszahl zwischen 1 und 100. inklusive 100.
random(-3, 6) eine zwischen -3 und 6. Inklusive 0.
Soweit, so einfach.
Schon etwas schwieriger ist es, aus 49 Zahlen zB 7 Zahlen zu ziehen, von denen keine mehrmals vorkommen darf. Dazu braucht man einen Korb mit Kugel, die man herausnimmt.
Zuerst also den Korb füllen und dann ziehen:
on RandomJeEinmal
--Hilfsliste, linear = Korb mit Kugel
tListe = []
repeat with i = 1 to 49
append tListe, i
end repeat
Liste = []
repeat with i = 1 to 7
r = random(count(tListe)) --wieviele Kugeln sind noch drin?
append Liste, tListe[r] --Kugel ziehen
deleteAt(tListe, r) --und aus Korb entfernen
end repeat
end
Nicht lineare Zufälle
Häufig gibt es den Fall, dass es eine bestimmte Tendenz geben soll. Etwa: eher niedrige Zahlen, eher hohe oder eher in einem bestimmten Bereich.
Der Trick ist, Zufallszahlen aus Zufallszahlen zu ziehen.
Ergebnis = random(random(random(100)))
Das kann durchaus auch 100 ergeben, aber der Durchschnitt aller gezogenen Zahlen geht eher Richtung ((100/2)/2)/2= 12,5
In Wahrheit etwas mehr, weil die Zahl 0 fehlt, die ja hier nie gezogen wird.
Fallstricke und Stolpersteine
In Lingo beginnen Listenindizes immer mit 1. Vorsicht ist also mit der Null geboten, die sich schnell einmal einschleichen kann:
Zahl = Kugeln - random(kugeln)
put Liste[Zahl]
Das kann ins Auge gehen! 49 - random(49) ergibt zB niemals 49, sondern höchstens 48, aber durchaus 0. Und: Liste[0] = Scriptfehler
Also:
Zahl = 1 + Kugeln - random(kugeln)
Bei komplexeren Formel kann es also leicht passieren, dass entweder doch einmal auf Liste[0] zugegriffen wird oder - und das ist etwas hinterhältiger: dass das letzte Listenelement vergessen
wird. Es würde ja nicht sofort auffallen, wenn im Lotto niemals die Zahl 49 vorkommt. Peinlich wäre es aber schon...
Wer einmal so einen kleinen Denkfehler gemacht hat, wird ihn durch Stochern im Code kaum mehr finden. Besser ist die direkte Überprüfung mit Repeat-Schleifen
Minimum = the maxinteger
Maximum = 0 - the maxinteger
repeat with i = 1 to the maxinteger
--Rechnungen...
if ergebnis < Minimum then Minimum = ergebnis
if ergebnis > Maximum then Maximum = ergebnis
end repeat
Put Minimum && Maximum
Bei so vielen Versuchen sollte wohl jedes Ergebnis einmal dabei gewesen sein. Wenn möglich sollte man natürlich auch die Parameter durchlaufen lassen. Diese Berechnung kann schon
ein Weilchen dauern, aber das macht man ja nur während des Authoring.
Wiederholungen vermeiden
Natürlich können sich 2 oder mehr Zahlen wiederholen. Bei einem Spiel sieht das aber gar nicht gut aus, wenn man gerade mal einen Level gemeistert hat und dann kommt im nächsten
Level dasselbe nocheinmal. Hier sollte man eine Liste der letzten wesentlichen Parameter mitführen:
on NaechstenLevelMachen
global BisherigeErgebnisse
--Berechnen...
if voidP(BisherigeErgebnisse) then BisherigeErgebnisse = []
if getPos(BisherigeErgebnisse, Ergebnis) > 0 then
NaechstenLevelMachen
exit
else
append BisherigeErgebnisse, Ergebnis
if count(BisherigeErgebnisse) > 3 then deleteAt(BisherigeErgebnisse, 1)
end if
end
Einen Handler (hier NaechstenLevelMachen) in sich selbst aufzurufen kann mitunter zu Endlosschleifen führen. In jedem Fall unmittelbar dahinter exit oder abort.
Noch besser: Notbremse einbauen.
|