Lottozahlen generieren |
|
| System | Win9x, WinNT, Win2000, WinXP, Vista, Win7 |
|---|---|
| Ab Delphi-Version | Delphi 4 |
| Letzte Änderung | 21.01.2012 |
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
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:
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 0 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
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:
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
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:
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.