Entwickler-Ecke
Sonstiges (Delphi) - Shuffle auf Inhalt eines Array of String
Basti22 - Sa 03.04.10 05:24
Titel: Shuffle auf Inhalt eines Array of String
Hi,
hab folgendes Problem.
Ich möchte den Inhalt eines Array of String "durchmischen".
Hab im Netz auch ein Beispiel mit einem Integer Array gefunden.
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:
| procedure ShuffleArray(aData: PIntegerArray; aMin, aMax: Integer; aIterations: Integer); var Source, Dest, Temp: Integer; begin while aIterations > 0 do begin Source := RandomRange(aMin, aMax); Dest := RandomRange(aMin, aMax); Temp := aData^[Source]; aData^[Source] := aData^[Dest]; aData^[Dest] := Temp; Dec(aIterations); end; end; |
mein Code:
Delphi-Quelltext
1: 2: 3:
| randomNames: Array[0..11] of string;
ShuffleArray(randomNames, 0, countPlayer, 5); |
habe jetzt versucht dieses Beispiel für meine "StringArray" zu nutzen, aber da meckert der Compiler.
[DCC Error] xyz.pas(162): E2010 Incompatible types: 'PIntegerArray' and 'Array'
Einen PStringArray scheint es nicht zu geben... habe da zummindest nichts im Netz gefunden und auch keine andere
Möglichkeit das zu umgehen.
Hoffe ihr könnt mir da helfen.
PS. meine Programmierkentnisse beschränken sich auf Schulniveau und das ist auch schon bald 10 Jahre her, also bitte keine super komplizierten antworten.... Danke :)
Moderiert von
Narses: Code- durch Delphi-Tags ersetzt
elundril - Sa 03.04.10 05:45
nimm doch den code aus diesem Library-Eintrag:
http://www.delphi-library.de/viewtopic.php?t=71713
damit bekommst du eine perfekte Permutation (dem Titel nach). Funktioniert ganz mit Strings, Integer, Records, Objekten und vielem mehr.
lg elundril
jaenicke - Sa 03.04.10 09:07
Basti22 hat folgendes geschrieben : |
Einen PStringArray scheint es nicht zu geben... habe da zummindest nichts im Netz gefunden und auch keine andere
Möglichkeit das zu umgehen. |
Dann schreib die Deklaration halt kurz hin... :roll:
Delphi-Quelltext
1: 2:
| TStringArray = array of String; PStringArray = ^TStringArray; |
Martok - Sa 03.04.10 13:30
Was ich da gemacht hab, wenn ich nicht für jeden Typ ein eigenes Shuffle will:
ich habe eine Funktion, die mir ein IntegerArray baut, dass die Indizes im Array enthält. Also z.b. [1,2,3,4,...,98,99,100].
Dann mische ich dieses Array, und benutze die gemischten Indizes zum Zugriff.
Pseudocode
1: 2: 3: 4:
| IndexArray:= MakeIndexArray(1,100); ShuffleFisherYates(IndexArray); for i in 1..100 do UseValue(ComplexDataArray[IndexArray[i]]); |
Basti22 - Sa 03.04.10 14:10
Hey vielen Dank euch dreien für die guten Ansätze... leider bekomme ich keinen so richtig zum laufen :oops:
da fehlen wohl doch nen paar Grundlagen bei mir :cry:
ich hab mich jetzt mal auf den Mischen nach Fisher-Yates aka Perfect Shuffle konzentriert... der klingt so toll ;)
hier mal am besten sinnvollerweise den ganzen Code
(kommt aus dem Spiel UltraStar (Singstar für PC)
mir geht es darum im Partymodus die eingegebenen Namen per Tastendruck durch zu mischen
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: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463:
| unit UScreenPartyPlayer;
Interface
uses UMenu, SDL, UDisplay, UMusic, UFiles, SysUtils, UThemes, Math;
type
TArrayElement = String; TArray = array of TArrayElement;
TScreenPartyPlayer = class(TMenu) public Team1Name: Cardinal; Player1Name: Cardinal; Player2Name: Cardinal; Player3Name: Cardinal; Player4Name: Cardinal;
Team2Name: Cardinal; Player5Name: Cardinal; Player6Name: Cardinal; Player7Name: Cardinal; Player8Name: Cardinal;
Team3Name: Cardinal; Player9Name: Cardinal; Player10Name: Cardinal; Player11Name: Cardinal; Player12Name: Cardinal;
constructor Create; override; function ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; override; procedure onShow; override; procedure SetAnimationProgress(Progress: real); override; end;
const ID='ID_016'; implementation
uses UGraphic, UMain, UIni, UTexture, UParty, UHelp, ULog;
function TScreenPartyPlayer.ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; var I, J, countPlayer: integer; SDL_ModState: Word; randomNames: Array[0..11] of String; procedure IntNext; begin repeat InteractNext; until Button[Interaction].Visible; end; procedure IntPrev; begin repeat InteractPrev; until Button[Interaction].Visible; end;
procedure ShuffleNames(var aArray: TArray); var i,j: Integer; tmp: TArrayElement; begin for i := Low(aArray) to High(aArray) do begin j := i +Random(Length(aArray) -i +Low(aArray)); tmp := aArray[j]; aArray[j] := aArray[i]; aArray[i] := tmp; end; end;
begin
Result := true; If (PressedDown) Then
SDL_ModState := SDL_GetModState and (KMOD_LSHIFT + KMOD_RSHIFT + KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT + KMOD_RALT);
begin case PressedKey of SDLK_TAB: begin ScreenPopupHelp.ShowPopup(); end;
SDLK_0..SDLK_9, SDLK_A..SDLK_Z, SDLK_SPACE, SDLK_MINUS, SDLK_EXCLAIM, SDLK_COMMA, SDLK_SLASH, SDLK_ASTERISK, SDLK_QUESTION, SDLK_QUOTE, SDLK_QUOTEDBL: begin Button[Interaction].Text[0].Text := Button[Interaction].Text[0].Text + chr(ScanCode); end;
SDLK_F1: if (SDL_ModState = KMOD_LALT) then begin
countPlayer := 0;
If (PartySession.Teams.NumTeams>=1) then begin If (PartySession.Teams.Teaminfo[0].NumPlayers >=1) then begin randomNames[countPlayer] := 'test'; inc(countPlayer); end; If (PartySession.Teams.Teaminfo[0].NumPlayers >=2) then begin inc(countPlayer); end; If (PartySession.Teams.Teaminfo[0].NumPlayers >=3) then begin inc(countPlayer); end; If (PartySession.Teams.Teaminfo[0].NumPlayers >=4) then begin inc(countPlayer); end; end;
If (PartySession.Teams.NumTeams>=2) then begin If (PartySession.Teams.Teaminfo[1].NumPlayers >=1) then begin inc(countPlayer); end; If (PartySession.Teams.Teaminfo[1].NumPlayers >=2) then begin inc(countPlayer); end; If (PartySession.Teams.Teaminfo[1].NumPlayers >=3) then begin inc(countPlayer); end; If (PartySession.Teams.Teaminfo[1].NumPlayers >=4) then begin inc(countPlayer); end; end;
If (PartySession.Teams.NumTeams>=3) then begin If (PartySession.Teams.Teaminfo[2].NumPlayers >=1) then begin inc(countPlayer); end; If (PartySession.Teams.Teaminfo[2].NumPlayers >=2) then begin inc(countPlayer); end; If (PartySession.Teams.Teaminfo[2].NumPlayers >=3) then begin inc(countPlayer); end; If (PartySession.Teams.Teaminfo[2].NumPlayers >=4) then begin inc(countPlayer); end; end;
ShuffleNames(randomNames[countPlayer]);
end;
SDLK_F2: if (SDL_ModState = KMOD_LALT) then begin Ini.NameTemplate[1] := Button[Interaction].Text[0].Text; end else begin Button[Interaction].Text[0].Text := Ini.NameTemplate[1]; end; SDLK_F3: if (SDL_ModState = KMOD_LALT) then begin Ini.NameTemplate[2] := Button[Interaction].Text[0].Text; end else begin Button[Interaction].Text[0].Text := Ini.NameTemplate[2]; end; SDLK_F4: if (SDL_ModState = KMOD_LALT) then begin Ini.NameTemplate[3] := Button[Interaction].Text[0].Text; end else begin Button[Interaction].Text[0].Text := Ini.NameTemplate[3]; end; SDLK_F5: if (SDL_ModState = KMOD_LALT) then begin Ini.NameTemplate[4] := Button[Interaction].Text[0].Text; end else begin Button[Interaction].Text[0].Text := Ini.NameTemplate[4]; end; SDLK_F6: if (SDL_ModState = KMOD_LALT) then begin Ini.NameTemplate[5] := Button[Interaction].Text[0].Text; end else begin Button[Interaction].Text[0].Text := Ini.NameTemplate[5]; end; SDLK_F7: if (SDL_ModState = KMOD_LALT) then begin Ini.NameTemplate[6] := Button[Interaction].Text[0].Text; end else begin Button[Interaction].Text[0].Text := Ini.NameTemplate[6]; end; SDLK_F8: if (SDL_ModState = KMOD_LALT) then begin Ini.NameTemplate[7] := Button[Interaction].Text[0].Text; end else begin Button[Interaction].Text[0].Text := Ini.NameTemplate[7]; end; SDLK_F9: if (SDL_ModState = KMOD_LALT) then begin Ini.NameTemplate[8] := Button[Interaction].Text[0].Text; end else begin Button[Interaction].Text[0].Text := Ini.NameTemplate[8]; end; SDLK_F10: if (SDL_ModState = KMOD_LALT) then begin Ini.NameTemplate[9] := Button[Interaction].Text[0].Text; end else begin Button[Interaction].Text[0].Text := Ini.NameTemplate[9]; end; SDLK_F11: if (SDL_ModState = KMOD_LALT) then begin Ini.NameTemplate[10] := Button[Interaction].Text[0].Text; end else begin Button[Interaction].Text[0].Text := Ini.NameTemplate[10]; end; SDLK_F12: if (SDL_ModState = KMOD_LALT) then begin Ini.NameTemplate[11] := Button[Interaction].Text[0].Text; end else begin Button[Interaction].Text[0].Text := Ini.NameTemplate[11]; end;
SDLK_BACKSPACE: begin Button[Interaction].Text[0].DeleteLastL; end;
SDLK_ESCAPE : begin Ini.SaveNames; Music.PlayBack; FadeTo(@ScreenPartyOptions); end;
SDLK_RETURN: begin Ini.SaveNames; for I := 0 to PartySession.Teams.NumTeams-1 do begin PartySession.Teams.Teaminfo[I].Name := PChar(Button[I*5].Text[0].Text); for J := 0 to PartySession.Teams.Teaminfo[I].NumPlayers-1 do begin PartySession.Teams.Teaminfo[I].Playerinfo[J].Name := PChar(Button[I*5 + J+1].Text[0].Text); PartySession.Teams.Teaminfo[I].Playerinfo[J].TimesPlayed := 0; end; end;
Music.PlayStart; FadeTo(@ScreenPartyNewRound); end;
SDLK_DOWN: IntNext; SDLK_UP: IntPrev; SDLK_RIGHT: IntNext; SDLK_LEFT: IntPrev; end; end; end;
constructor TScreenPartyPlayer.Create; var I: integer; begin inherited Create;
LoadFromTheme(Theme.PartyPlayer);
Team1Name := AddButton(Theme.PartyPlayer.Team1Name); AddButton(Theme.PartyPlayer.Player1Name); AddButton(Theme.PartyPlayer.Player2Name); AddButton(Theme.PartyPlayer.Player3Name); AddButton(Theme.PartyPlayer.Player4Name);
Team2Name := AddButton(Theme.PartyPlayer.Team2Name); AddButton(Theme.PartyPlayer.Player5Name); AddButton(Theme.PartyPlayer.Player6Name); AddButton(Theme.PartyPlayer.Player7Name); AddButton(Theme.PartyPlayer.Player8Name);
Team3Name := AddButton(Theme.PartyPlayer.Team3Name); AddButton(Theme.PartyPlayer.Player9Name); AddButton(Theme.PartyPlayer.Player10Name); AddButton(Theme.PartyPlayer.Player11Name); AddButton(Theme.PartyPlayer.Player12Name);
Interaction := 0; end;
procedure TScreenPartyPlayer.onShow; var I: integer; begin if not Help.SetHelpID(ID) then Log.LogError('No Entry for Help-ID ' + ID + ' (ScreenPartyPlayer)');
for I := 1 to 4 do Button[I].Text[0].Text := Ini.Name[I-1];
for I := 6 to 9 do Button[I].Text[0].Text := Ini.Name[I-2];
for I := 11 to 14 do Button[I].Text[0].Text := Ini.Name[I-3];
Button[0].Text[0].Text := Ini.NameTeam[0]; Button[5].Text[0].Text := Ini.NameTeam[1]; Button[10].Text[0].Text := Ini.NameTeam[2];
If (PartySession.Teams.NumTeams>=1) then begin Button[1].Visible := (PartySession.Teams.Teaminfo[0].NumPlayers >=1); Button[2].Visible := (PartySession.Teams.Teaminfo[0].NumPlayers >=2); Button[3].Visible := (PartySession.Teams.Teaminfo[0].NumPlayers >=3); Button[4].Visible := (PartySession.Teams.Teaminfo[0].NumPlayers >=4); end else begin Button[0].Visible := False; Button[1].Visible := False; Button[2].Visible := False; Button[3].Visible := False; Button[4].Visible := False; end;
If (PartySession.Teams.NumTeams>=2) then begin Button[5].Visible := True; Button[6].Visible := (PartySession.Teams.Teaminfo[1].NumPlayers >=1); Button[7].Visible := (PartySession.Teams.Teaminfo[1].NumPlayers >=2); Button[8].Visible := (PartySession.Teams.Teaminfo[1].NumPlayers >=3); Button[9].Visible := (PartySession.Teams.Teaminfo[1].NumPlayers >=4); end else begin Button[5].Visible := False; Button[6].Visible := False; Button[7].Visible := False; Button[8].Visible := False; Button[9].Visible := False; end;
If (PartySession.Teams.NumTeams>=3) then begin Button[10].Visible := True; Button[11].Visible := (PartySession.Teams.Teaminfo[2].NumPlayers >=1); Button[12].Visible := (PartySession.Teams.Teaminfo[2].NumPlayers >=2); Button[13].Visible := (PartySession.Teams.Teaminfo[2].NumPlayers >=3); Button[14].Visible := (PartySession.Teams.Teaminfo[2].NumPlayers >=4); end else begin Button[10].Visible := False; Button[11].Visible := False; Button[12].Visible := False; Button[13].Visible := False; Button[14].Visible := False; end;
end;
procedure TScreenPartyPlayer.SetAnimationProgress(Progress: real); var I: integer; begin for I := 0 to high(Button) do Button[I].Texture.ScaleW := Progress; end;
end. |
Zeile 10,11 hab ich jetzt eingefügt.
Zeile 37 auch, wenn ich die NICHT auskommentiere bekomme ich die Meldung "[DCC Error] UScreenPartyPlayer.pas(37): E2065 Unsatisfied forward or external declaration: 'TScreenPartyPlayer.ShuffleNames'"
was ist da falsch?
hab dann die Procedure einfach etwas vor meinen Aufruf geschrieben... ich weiß.. nicht so toll :oops:
Zeile 188 ist jetzt das eigentliche Problem, da sagt er mir "[DCC Error] UScreenPartyPlayer.pas(188): E2033 Types of actual and formal var parameters must be identical"
hab dann testweise den Array in Zeile 53 in
randomNames: Array[0..11] of TArrayElement;
geändert.... dann hatte er das nicht mehr angemeckert, ich konnta aber in meinen Array auch keine Strings mehr reinschreiben (z.B. Zeile 120 oder 125 + folgende) (<<--- gerade beim hier posten bekomme ich den E2033 so auch nicht mehr weg :roll: )
ihr seht schon... bin da nicht der Profi :oops:
hoffe ihr könnte mir trotzdem noch ein bischen helfen
Moderiert von
Narses: Code- durch Delphi-Tags ersetzt
jaenicke - Sa 03.04.10 14:27
Der erste Fehler: Oben schreibst du unter public, dass es ein ShuffleNames in TScreenPartyPlayer gebe, dann aber gibt es unten nur eine Prozedur ShuffleNames, die nicht als Methode in TScreenPartyPlayer drin ist (steht ja auch kein TScreenPartyPlayer. dabei wie bei ParseInput).
Basti22 - Sa 03.04.10 14:40
jaenicke hat folgendes geschrieben : |
| Der erste Fehler: Oben schreibst du unter public, dass es ein ShuffleNames in TScreenPartyPlayer gebe, dann aber gibt es unten nur eine Prozedur ShuffleNames, die nicht als Methode in TScreenPartyPlayer drin ist (steht ja auch kein TScreenPartyPlayer. dabei wie bei ParseInput). |
Na das klingt ja irgendwie logisch :oops:
Hab jetzt meine Procedure in
Delphi-Quelltext
1:
| procedure TScreenPartyPlayer.ShuffleNames(var aArray: TArray); |
umgeschrieben und ganz ans Ende verschoben. Das scheint jetzt zu gehen.
Mein
[DCC Error] UScreenPartyPlayer.pas(173): E2033 Types of actual and formal var parameters must be identical Fehler ist trotzdem noch da :(
egal ob ich in Zeile 53
Delphi-Quelltext
1: 2: 3: 4: 5:
| randomNames: Array[0..11] of String;
randomNames: Array[0..11] of TArrayElement; |
stehen hab
//edit:
gerade gemerkt: TArrayElement ist ja falsch... ist ja nur nen String :oops:
also wenn ich
Delphi-Quelltext
1:
| randomNames: Array[0..11] of String; |
schreibe bekomm ich den E2033 Fehler..
wenn ich
Delphi-Quelltext
1:
| randomNames: Array[0..11] of TArray; |
schreibe bekomm ich
[DCC Error] UScreenPartyPlayer.pas(105): E2010 Incompatible types: 'TArray' and 'string'
+ den E2033 und kann keine Strings mehr in den Array schreiben
... versteh ich nicht so ganz... hab doch nen Array mit Strings als Inhalt :?:
Moderiert von
Narses: Code- durch Delphi-Tags ersetzt
jaenicke - Sa 03.04.10 15:35
Du deklarierst ein festes Array of String und willst das als TArray (ein dynamisches Array of String) benutzen, das kann nicht gehen. Der Typ ist TArray, Punkt, das musst du auch als Typ für deine Variable nutzen.
Basti22 - Sa 03.04.10 16:35
Es geht wie geil :D
Musste zwar noch ne ganze Weile grübeln, stand da irgendwie auf dem Schlauch, aber jetzt funktioniert es wunderbar :)
Vielen Dank nochmal für die Hilfe
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!