Home » Tipps & Tricks » Algorithmen » Sonstiges » Lottozahlen generieren

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.