Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Zufallsgenerator mehrmals starten


ggehrma - So 25.09.05 12:49
Titel: Zufallsgenerator mehrmals starten
Hallo,

Ich habe folgendes Problem:
Ich möchte eine Menge von Zahlen in eine zufällige Reihenfolge bringen. Ich hab das jetzt so gemacht, dass ich die Zahlen alle in eine StringList geschrieben habe und dann über Randomize und Random einen zufälligen Index der StringList herausgesucht habe. Wenn ich jetzt den Vorgang erneut mit der ursprünglichen Liste starte, kommt wieder die gleiche Reihenfolge wie beim ersten Mal.
Kann ich das irgendwie ändern oder liegt das an Randomize + Random und kann nicht verändert werden?

mfg, ggehrma


starsurfer - So 25.09.05 13:00

das dürfte nich passieren....poste mal bitte deinen code

gugg ev mal hier rein: http://www.delphi-forum.de/viewtopic.php?t=48428&highlight=


ggehrma - So 25.09.05 13:10

Hier ist der Code:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
procedure TfrmMain.btnShuffleClick(Sender: TObject);
//Zufallsliste erstellen
var i,x: Integer;
    RandomIndex: Integer;
    Shuffle: PShuffle;
//i,x: Zählvariablen
//RandomIndex: Index des Zufallstracks
//Shuffle: Pointervariable auf den neu definierten Typ
begin
  //Titel-Tabelle leeren
  lsvTracklist.Clear;
  ShuffleList.Create;
  i := 0;
  //Zufallsgenerator starten
  Randomize;
  REPEAT
    //Zufalls-Track heraussuchen
    RandomIndex := Random(TrackList.Count);
    //Wenn der Track noch nicht in der Zufallsliste ist,
    IF ShuffleList.IndexOf(IntToStr(RandomIndex)) = -1 THEN
      //nehme ihn in die Zufallsliste mit auf
      ShuffleList.Add(IntToStr(RandomIndex));
    //Wenn die Track-Anzahl der Zufallsliste = der Anzahl der geordneten Liste ist,
    IF ShuffleList.Count = TrackList.Count THEN
      i := 1;
    //beende den Zufallsgenerator
  UNTIL i = 1;
  FOR x := 0 TO TrackList.Count - 1 DO BEGIN
    Shuffle := PShuffle(TrackList.Objects[x]);
    //Den Index auf der geordneten Titelliste dem Zufallsstück zuweisen
    Shuffle.ShuffleIndex := StrToInt(ShuffleList.Strings[x]);
  END;
  //Anzeigen der Zufallsliste in der Tabelle
  FOR x := 0 TO ShuffleList.Count-1 DO BEGIN
    Shuffle := PShuffle(TrackList.Objects[x]);
    WITH lsvTrackList.Items.Add DO BEGIN
      Caption := IntToStr(x+1);
      //Dateiname
      SubItems.Add(ExtractFileName(TrackList.Strings[Shuffle.ShuffleIndex]));
      //Dateipfad
      SubItems.Add(ExtractFilePath(TrackList.Strings[Shuffle.ShuffleIndex]));
      SubItems.Add(IntToStr(Shuffle.ShuffleIndex));
    END;
  END;
end;


delfiphan - So 25.09.05 13:24

Randomize musst du nur ein mal beim Start des Programmes ausführen.


alzaimar - So 25.09.05 13:34

Ganz einfach, nachdem Du korrekt (vielleicht ein wenig umständlich) die ShuffleList erzeugst, verwendest Du sie gar nicht!.
Hier ist eine bessere (und schnellere) Möglichkeit, eine ShuffleList zu erzeugen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
Var
  ShuffleList : Array Of Integer;
  h,n,i,j : Integer;

Begin
  n := TrackList.Count;
  setLength (ShuffleList, n);
  For i:=0 to n-1 do ShuffleList[i] := i;  // erstmal eine geordnete Liste erstellen
  For i:=0 to n-1 do Begin      // Für alle Elemente der Liste
    j := Random (n - i + 1);      // ein zufälliges Element 0.. n-i auswählen
    h := ShuffleList[j];      // und vertauschen
    ShuffleList[j] := ShuffleList[i]; 
    ShuffleList[i] := h;
    End;
End;


ggehrma - So 25.09.05 13:46

Na klar verwende ich die ShuffleList:

Delphi-Quelltext
1:
Shuffle.ShuffleIndex := StrToInt(ShuffleList.Strings[x]);                    


@alzaimar:
Leider kann ich deine Version nicht verwenden, da ich meinen Record auf den ich über die Variable Shuffle zugreife noch weiter benötige.

Wenn ich Randomize nur einmal ganz am Anfang des Programms ausführe, passiert leider der selbe Fehler.


ggehrma - So 25.09.05 13:57

OK, hab das Problem jetzt selber gelöst:

Hab einfach statt ShuffleList.Create ein ShuffleList.Clear gesetzt und das ShuffleList.Create ganz an den Programm-Anfang.

Trotzdem Danke für eure Vorschläge.