Lottozahlen generieren
Eine beliebte Aufgabe, die gerne Programmieranfängern gestellt wird, ist die Simulation einer Lotto-Ziehung. Die folgenden Funktionen ermöglichen jeweils eine solche Simulation, wobei nicht nur das hier in Deutschland gespielte „6 aus 49“ simuliert wedren kann, sondern auch z.B. „6 aus 45″(Österreich), „9 aus 90″(Italien) oder „7 aus 35″(Schweden).
Da es hier – wie so oft – mehr als eine mögliche Lösung gibt, werden hier drei Möglichkeiten vorgestellt. Der Algorithmus ist jeweis der selbe, sodass sich die einzelnen Lösungen nur im Typ des Rückgabewertes unterscheiden:
Möglichkeit 1 – array of Integer
type TLottoResult = array of Integer; ... implementation function Lotto(ACount: Integer; AMaxValue: Integer): TLottoResult; var i, j: integer; number: integer; newNumberFound: Boolean; begin if ACount > AMaxValue then raise EInvalidOp.Create('Man kann nicht mehr Elemente aus einer Menge ziehen, als vorhanden!'); SetLength(Result, ACount); for i := 0 to high(Result) do begin repeat number := Random(AMaxValue) +1; newNumberFound := True; //prüfen ob die Zahl schon gezogen wurde for j := 0 to i-1 do begin if (Result[j] = number) then begin newNumberFound := False; break; // nicht nötig, macht das Ganze aber etwas schneller end; end; Result[i] := number; until newNumberFound; //Solange wiederholen, bis die Schleife durchgelaufen ist end; end; ... initialization Randomize;
Ein Aufruf sieht dann z.B. so aus:
procedure TForm1.Button1Click(Sender: TObject); var lottoResult: TLottoResult; i: integer; begin lottoResult := Lotto(6, 49); Memo1.Clear; for i := 0 to high(lottoResult) do Memo1.Lines.Add(IntToStr(lottoResult[i])); end;
Um die Lottoziehung zu simulieren, wird die Funktion Random(AMaxValue)
verwendet. Diese liefert eine Zahl zwischen und
AMaxValue - 1
. Um eine Zahl zwischen 1
und AMaxValue
zu bekommen, addieren wir einfach 1
.
Damit Random
auch richtig funktioniert, muss der Zufallsgenerator zuerst mit Randomize
initialisiert werden. Dies geschieht hier im initialization
-Abschnitt der Unit. Wenn ein Formular vorhanden ist, kann man das natürlich auch in OnCreate
machen. Wichtig ist nur, dass Randomize
nur einmal aufgerufen wird.
Um zu vermeiden, dass mehrmals die selbe Zahl gezogen wird, wird in einer repeat
-Schleife so lange nach einer neuen Zahl gesicht, bis eine gefunden wird.
Möglichkeit 2 – StringList
procedure Lotto(ACount, AMaxValue : Integer; AResult: TStrings) ; var i : Integer; number :string; begin if ACount > AMaxValue then raise EInvalidOp.Create('Man kann nicht mehr Elemente aus einer Menge ziehen, als vorhanden!'); AResult.Clear; for i := 1 to ACount do begin repeat number := IntToStr(Random(AMaxValue) + 1); until AResult.IndexOf(number) = -1; AResult.Add(number); end; end; ... initialization Randomize;
Aufruf:
procedure TForm1.Button1Click(Sender: TObject); var i: integer; begin Lotto(6, 49, Memo1.Lines); end;
Hier wird statt dem array of Integer
direkt auf einer String-Liste gearbeitet. Das ist etwas langsamer, macht aber die Anzeige einfacher.
Möglichkeit 3 – Sets
type TLottoResult = set of 1..255; ... implementation function Lotto(ACount : Byte; AMaxValue : Byte) : TLottoResult; var i: Byte; number: Byte; begin if ACount > AMaxValue then raise EInvalidOp.Create('Man kann nicht mehr Elemente aus einer Menge ziehen, als vorhanden!'); Result := []; for i := 1 to ACount do begin repeat number := Random(aMaxValue) + 1; until not(number in Result); Include(Result, number); end; end; ... initialization Randomize;
Aufruf:
procedure TForm1.Button1Click(Sender: TObject); var lottoResult: TLottoResult; i: Byte; begin lottoResult := Lotto(6, 49); for i := 0 to 49 do begin if i in LottoResult then Memo1.Lines.Add(IntToStr(i)); end; end;
Hier werden Mengentypen – so genannte Sets – verwendet um das Ergebnis aufzunehmen. Der Vorteil hierbei ist das einfache Testen auf das Vorhandensein in der Menge. Dadurch wird die eigentliche Lotto-Funktion recht einfach. Ebenso ist die Ausgabe „automatisch“ sortiert, da es in Sets keine Reihenfolge gibt und wir diese also indirekt bestimmen können, indem wir einfach aufteigend die Zahlen testen(for i := 0 to 49 do
). Der Nachteil ist, dass die Ausgabe vergeleichsweise aufwändig ist.