![]() |
Random ohne Dublette
Ich möchte z.B. eine Zufallszahl von 1...6 ausgeben. Kommt dann als erstes die 3, so soll sie bei dem nächsten Buttonclick nicht mehr kommen, d.h. die möglichen Zahlen, aus denen die neue Zufallszahl gebildet wird, nehmen um 1 ab, bis keine mehr vorhanden ist.
Das Grundprinzip ist mir klar - wie kann ich jedoch die Dubletten vermeiden und eine Zahl die schonmal erschienen ist nicht mehr ausgeben lassen. Danke für die Hilfe.
Delphi-Quellcode:
[edit=SirThornberry]Delphi-Tags gesetzt - Mfg, SirThornberry[/edit]
var
Form1: TForm1; Zufall: Integer; procedure TForm1.Button1Click(Sender: TObject); begin randomize; Zufall:= random (5)+1; Label1.Caption:=IntToStr (Zufall); end; end. |
Re: Random ohne Dublette
Hallo,
das ist ganz einfach. Du musst Dir nur merken, welche Zahl schon gekommen ist:
Delphi-Quellcode:
Gruß
var
SchonGehabt: array [1..6] of Boolean; // Zurücksetzen procedure InitRandom; var I: Integer; begin for I := 1 to 6 do SchonGehabt[I] := False; end; // Zufallszahl erzeugen function GetRandom: Integer; begin repeat Result := Random(6) + 1; until not SchonGehabt[Result]; SchonGehabt[Result] := True; end; //Aufruf: procedure TForm1.FormCreate(Sender: TObject); begin Randomize; InitRandom; end; procedure TForm1.Button1Click(Sender: TObject); begin Zufall:= GetRandom; Label1.Caption := IntToStr(Zufall); end; xaromz |
Re: Random ohne Dublette
Die einfachste Methode ist das Sortieren umzukehren. Erst eine Liste von 6 Zahlen erstellen und sie dann durcheinanderbringen.
Einfach mehrfach zwei Zahlen zufaellig gewaehlt vertauschen. |
Re: Random ohne Dublette
Moin!
@xaromz: Klasse Endlosschleife beim 6. Aufruf :zwinker: Eine Möglichkeit:
Delphi-Quellcode:
Eine andere Möglichkeit:
var
Index:Byte; Zahlen:Array [1..6] of Byte; // Zurücksetzen procedure InitRandom; var i, p1, p2, temp:Byte; begin Index:=0; For i:=1 to 6 do Zahlen[i]:=i; For i:=1 to 100 do begin p1:=Random(6)+1; p2:=Random(6)+1; If p1=p2 then Continue; temp:=Zahlen[p1]; Zahlen[p1]:=Zahlen[p2]; Zahlen[p2]:=temp; end; end; // Zufallszahl erzeugen function GetRandom(const Index:Byte):Byte; begin Case Index of 1..6: Result:=Zahlen[Index]; else Result:=0; end; end; procedure TForm1.FormCreate(Sender: TObject); begin Randomize; InitRandom; end; //Aufruf: procedure TForm1.Button1Click(Sender: TObject); var Zufall:Byte; begin If Index=6 then begin InitRandom; Label1.Caption:=''; end; Inc(Index, 1); Zufall:=GetRandom(Index); Label1.Caption:=Label1.Caption+IntToStr(Zufall)+' '; end;
Delphi-Quellcode:
Grüßle!
var
List:TList; // Zurücksetzen procedure InitRandom; var i, p1, p2:Byte; temp:PByte; begin For i:=1 to 6 do begin New(temp); temp^:=i; List.Add(temp); end; For i:=1 to 100 do begin p1:=Random(6); p2:=Random(6); If p1=p2 then Continue; List.Exchange(p1, p2); end; end; procedure TForm1.FormCreate(Sender: TObject); begin List:=TList.Create; Randomize; InitRandom; end; //Aufruf: procedure TForm1.Button1Click(Sender: TObject); var Zufall:Byte; begin If List.Count=0 then begin InitRandom; Label1.Caption:=''; end; Zufall:=PByte(List[0])^; Dispose(List[0]); List.Delete(0); Label1.Caption:=Label1.Caption+IntToStr(Zufall)+' '; end; |
Re: Random ohne Dublette
Guten Morgen,
Zitat:
![]() Grüße vom marabu |
Re: Random ohne Dublette
Delphi-Quellcode:
Aufruf für deinen Fall dann Lotto(..,..., 6, 6);
type
TZahlen = array of Integer; procedure Lotto(var Sortiert,Gezogene: TZahlen; Ziehungen: Integer = 6; Elemente: Integer = 49); var I,J,K,N: Integer; begin Sortiert := nil; // stellt sicher das Sortiert <> Gezogene ist Gezogene := nil; if Ziehungen > Elemente then raise Exception.Create('Man kann nicht mehr Kugeln ziehen als in der Urne sind'); SetLength(Sortiert, Ziehungen); SetLength(Gezogene, Ziehungen); for I := 0 to Ziehungen -1 do begin K := 0; N := Random(Elemente - I) + 1; for J := 0 to I -1 do if N >= Sortiert[J] then begin Inc(N); Inc(K); end else Break; for J := I downto K +1 do Sortiert[J] := Sortiert[J -1]; Sortiert[K] := N; Gezogene[I] := N; end; end; Du kanst dir das so umbauen das der Parameter "Sortiert" als lokale Variable benuztzt wird, da du ja nur die gezogene Reihenfolge benötigst. Gruß Hagen PS: Zitat:
|
Re: Random ohne Dublette
Hallo Hagen,
wenn du meinem Link folgst, findest du eine Misch-Prozedur, welche für den Fall "n aus n" eine Urnenziehung (draw & remove) inplace ausführt. Nur für den Fall "n aus n" galt meine Aussage. Was daran sollte brute force sein? Freundliche Grüße |
Re: Random ohne Dublette
Hallo,
Zitat:
Gruß xaromz |
Re: Random ohne Dublette
Zitat:
Die Mischer-Methode ist deshalb nicht elegant weil sie aus meiner Sicht 1.) bei 6 Zahlen minimal 12 mal Random() aufruft. 2.) weil sie trivial ist, also das was man als normaler Programmierer als Worst-Case Lösung, wenn einem nichts anders mehr einfällt, benutzt. Mal ehrlich unter uns, was an dieser Methode ist so besonders elegant ? Brute Force bezog sich also auf die "Idee wie man es lösen" könnte, und Brute Force ist immer der letzte Schritt wenn alles andere keine Lösung ist. Die "Mischer-Methode" ist dann und nur dann elegant wenn die Aufgabenstellung nicht mehr das "Ziehen von x eindeutigen zufälligen Zahlen" ist sondern das "zufällige Mischen einer Menge von x Zahlen" ist. Und selbst dann sollte man mit x Aufrufen von Random() auskommen können. In deinem Falle solltest du also das Array nur von 0 bis x-1 durchgehen und das Element an diesem Index mit einem Element an einen zufälligen Index austauschen. Denn so vermeidest du das bei einem schlechten RNG und 2 zufälligen Indizes sich das ganze Mischen wieder aufhebt. Denoch entstehen Zufalls-Indizes die gleich sind, also zb. Austauschungen von Index 2 mit 1 und Index 3 mit 1. Die Wahrscheinlichkeiten ändern sich damit und sind NICHT identisch im Vergleich bei Ziehen von x eindeutigen Zahlen. Das habe ich aber schon im "Lotto" Thread erklärt. Sie ist aber insofern "elegant" wenn man aus der Menge der im WEB kursierenden Lösungen auswählen müsste, dann ist sie sogar schon fast super-elegant ;) Es geht aber eben noch besser aus meiner Sicht. Gruß Hagen |
Re: Random ohne Dublette
Lieber Hagen,
Zitat:
Zitat:
Zitat:
[equote="Prof. Beutelspacher in 'Das ist o.B.d.A. trivial'"]Trivial ist das Wort in mathematischen Texten, das am häufigsten falsch gebraucht wird. ... Damit bezeichnet man Argumente oder Eigenschaften, die sich ohne jedes Zutun aus einer Definition oder einem Satz ergeben. ... Bei richtigem Gebrauch des Wortes bewegt man sich auf einem schmalen Grat. Es ist manchmal eine Frage der mathematischen Vorbildung, was man als trivial bezeichnet.[/equote] Und negativ besetzt ist der Begriff auch nicht - wie man sieht. Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
BTW: Das soll der Fisher-Yates-Shuffle sein.
procedure Shuffle(var a: array of integer);
var i, j, temp: integer; begin for i := High(a) downto 1 do begin j := Random(i); temp := a[i]; a[i] := a[j]; a[j] := temp; end; end; Nachdenkliche Grüße |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz