Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Array an procedure übergeben (https://www.delphipraxis.net/13656-array-procedure-uebergeben.html)

Igotcha 23. Dez 2003 13:05


Array an procedure übergeben
 
Hallo zusammen,

folgendes Problem:

Ich habe ein dynamisches Array der Form

Delphi-Quellcode:
type EKarte = record
    name: string;
    ort: integer;
    status: integer;
end;
mit

Delphi-Quellcode:
P1EKarte, P2EKarte: Array of Ekarte;
und einem späteren

SetLength(P1EKarte,20).

Jetzt möchte ich das Array mischen und mir dazu eine Prozedur "mischen" schreiben, die von 0 bis High(P1EKarte) läuft und die Einträge von 0 bis zum Ende mit einem zufälligen Eintrag vertauscht. Dazu benötige ich aber ein Dummyrecord vom Typ EKarte als Zwischenspeicher.

Folgendes funktioniert schon mal nicht ;-)

Delphi-Quellcode:
procedure MixECards(PECards: Array of EKarte);
var
  CDummy: EKarte;
  ix: integer;
begin
    For ix:=0 to High(PECards) do
    begin
    CDummy:=Copy(PECards, ix, 1);
    end;
end;
Das Mischen selbst ist noch nicht implementiert, da ich hier bereits schon mit inkompatiblen Typen zu kämpfen habe.

Gruß Kay

[edit=sakura] [delphi]-Tags gesetzt. Mfg, sakura[/edit]

choose 23. Dez 2003 13:09

Re: Array an procedure übergeben
 
Hallo Igotcha,

die Erklärung für dieses Phänomens sowie eine brauchbare Lösung solltest Du in dem Thread array of String als Result einer Funktion finden.

Sanchez 23. Dez 2003 13:13

Re: Array an procedure übergeben
 
Zitat:

Zitat von Igotcha
procedure MixECards(PECards: Array of EKarte);
var
CDummy: EKarte;
ix: integer;
begin
For ix:=0 to High(PECards) do
begin
CDummy:=Copy(PECards, ix, 1);
end;
end;

Das Mischen selbst ist noch nicht implementiert, da ich hier bereits schon mit inkompatiblen Typen zu kämpfen habe.

Die inkompatiblen Typen bekommst du aber beim Copy.
Willst du einfach die EKarte am Index ix in CDummy kopieren?

Wenn ja dann so:

Delphi-Quellcode:
  CDummy := PECards[ix];
grüße, daniel

Igotcha 23. Dez 2003 14:52

Re: Array an procedure übergeben
 
Ja, beim Copy, stimmt.

CDummy := PECards[ix] funktioniert aber grundsätzlich.

Ich habe aber noch einen völlig anderen Denkfehler drin ;-) Das Array wird so natürlich in der Procedure schön gemischt, aber mein Input-Array nicht.

Ich benötige also folgendes:

Code:
GemischtesArray:=MixECards(UngemischtesArray);
oder

Code:
P1EKarte:=MixEcards(P1EKarte);
Wobei ein

Code:
P2EKarte:=MixEcards(P2EKarte) natürlich auch funktionieren sollte.
Das bekomme ich aber auch nicht so recht hin...

Gruß Kay

himitsu 23. Dez 2003 15:11

Re: Array an procedure übergeben
 
Meinst du das so etwa ?

Delphi-Quellcode:
Type EKarte = Record
    name: String;
    ort: Integer;
    status: Integer;
  End;
  AEKarte = Array of EKarte;

Var P1EKarte: AEKarte;

Procedure MixECards(Var PECards: AEKarte);
  Var CDummy: EKarte;
    ix, p1, p2: Integer;

  Begin
    //For ix := 0 to High(PECards) do
    //  CDummy := PECards[ix];
    For ix := 0 to 10000 do Begin
      p1 := Random(High(PECards)); //zu tauschende Karten ermitteln
      p2 := Random(High(PECards));
      CDummy := PECards[p1];      //Karten tauschen
      PECards[p1] := PECards[p2]
      PECards[p2] := CDummy;
    End;
  End;


...
MixECards(P1EKarte);

Igotcha 23. Dez 2003 15:49

Re: Array an procedure übergeben
 
Ich versuche es mal etwas ausführlicher:

Gegeben ist

Code:
Type EKarte = Record
    name: String;
    ort: Integer;
    status: Integer;
  End;
Davon gibt es nun für die beiden Spieler

Code:
var
   P1Ekarte, P2EKarte: Array of Ekarte
Diese beiden Arrays werden nun mit den Karten der Spieler geladen. Da es ist keine festgesetzte Anzahl von Karten gibt, wurde ein dynamisches Array verwendet (beim Laden wird mit Setlength jeweils die Endgröße der Arrays P1EKarte und P2EKarte bestimmt.

Jetzt soll eine Funktion / Prozedur existieren, die die gefüllten Arrays "mischt". Nach dem Mischen sollen in den beiden Arrays jeweils die ursprünglichen Karten vorhanden sein, nur gemischt.

Gesucht ist also ein Funktion / Prozedur "MixECards" in der Form:

Code:
P1EKarte (gemischt) :=MixECards(P1Ekarte (ungemischt));
die sich dann auch als

Code:
P2EKarte (gemischt) :=MixECards(P2Ekarte (ungemischt));
benutzen lassen sollte.

Wie schon geschrieben, ein Mischen innerhalb der Prozedur habe ich hinbekommen, nur blieb da mein Input-Array unverändert.

Code:
procedure MixECards(PECards: Array of EKarte);
begin
     ...
end;
Bei einem MixEcards(P1EKarte) wurde praktisch "PECards" innerhalb der Prozedur gemischt, aber nicht "P1EKarte" als Ergebnis.

Gruß Kay

choose 23. Dez 2003 15:56

Re: Array an procedure übergeben
 
In dem Thread, auf den ich in meinem vorherigen Posting verwiesen habe, würdest Du etwas in der Art
Delphi-Quellcode:
type
  TMyArray = array of TMyType;

function MyFunc(const AParam: TMyArray): TMyArray;
begin
  SetLength(Result, Length(AParam));
  //...
end;

//...
  AnArray:= MyFunc(AnotherArray);
finden...

himitsu 23. Dez 2003 16:32

Re: Array an procedure übergeben
 
Also dann so ?

Delphi-Quellcode:
Type EKarte = Record
    name: String;
    ort: Integer;
    status: Integer;
  End;
  AEKarte = Array of EKarte;

Var P1Ekarte, P2EKarte: AEKarte;

Procedure MixECards(Var PECards: AEKarte);
  Var CDummy: EKarte;
    ix, p1, p2: Integer;

  Begin
    For ix := 0 to 10000 do Begin {je mehr Durchgänge, desto mehr wird gemischt}
      //2 Karten durch Zufall auswählen, die getauscht werden sollen
      p1 := Random(High(PECards));
      p2 := Random(High(PECards));
      //die Beiden ermittelten Karten austauschen
      CDummy := PECards[p1];
      PECards[p1] := PECards[p2];
      PECards[p2] := CDummy;
    End;
  End;

IrgendeineProzedur/Funkktion;
  Begin
    ...
    {hier sind die Karten noch ungemischt}
    MixECards(P1EKarte);
    MixECards(P2EKarte);
    {und hier sind sie gemischt}
    ...
  End;


Sowas ist doch nicht nötig:
Delphi-Quellcode:
Function MixECards(PECards: AEKarte): AEKarte;
  ...


P1EKarte := MixECards(P1EKarte);
P2EKarte := MixECards(P2EKarte);
Es geht doch so viel einfacher:
Delphi-Quellcode:
Procedure MixECards(Var PECards: AEKarte);
  ...


MixECards(P1EKarte);
MixECards(P2EKarte);
Die Angabe von VAR in der Parameterdeklaration der Prozedur gibt an, dass der übergebene Parameter geändert werden kann, daher ist auch der Umweg über ein zweites Array nicht nötig.

Igotcha 23. Dez 2003 16:42

Re: Array an procedure übergeben
 
Zitat:

Zitat von choose
Delphi-Quellcode:
type EDummy = array of EDummy;
natürlich

und das habe ich geändert in

Delphi-Quellcode:
function MixECards(const AParam: EDummy): EDummy;

function MixECards(Var AParam: EDummy): EDummy;
Oh Mann, schwere Geburt, aber keine Typenfehler mehr ;-)

Vielen Dank Euch und ein frohes Fest...

Gruß Kay

choose 23. Dez 2003 16:48

Re: Array an procedure übergeben
 
Bitte ändere zunächst Deine Bezeichnungen. Typen, die mit einem großen "E" beginnen, haben in Delphi eine besondere Bedeutung...

Das Problem besteht erneut in den unterschiedlichen Typen TKarteArray (vormals EDummy) versus array of TKarte (vormals EKarte). Ändere einfach die Deklaration von P1EKarte entsprechend ab und es sollte funktionieren (abgesehen davon, dass Dir die Funktion MixCards (vormals MixECards) zwar ein Array der passenden größe allerdings mit nicht belegten Daten zurückgibt...).

himitsu 23. Dez 2003 16:49

Re: Array an procedure übergeben
 
Delphi hat mit zwar gleichen Typendeklaration einige Progleme.

So geht es NICHT:
Delphi-Quellcode:
type EDummy = array of EKarte;

function MixECards(const AParam: EDummy): EDummy;

var P1EKarte: Array of Ekarte;

{P1EKarte <> AParam}
So dürfte es geh'n:
Delphi-Quellcode:
type EDummy = array of EKarte;

function MixECards(const AParam: EDummy): EDummy;

var P1EKarte: EDummy;

{P1EKarte = AParam}

himitsu 23. Dez 2003 16:54

Re: Array an procedure übergeben
 
@choose:
Die Namen sind Delphi total egal.
Diese "Vorgaben" für die Namensvergabe (das hast du bestimmt irgendwo gelesen) ist nur zum einfachen lesen/verständnis der Quellcodes gedacht und hat nichts mit der Funktion zu tun.

Und das was Igotcha da geschrieben hat, sind mit Sicherheit nur Beispiele und sehen nicht im direkten Zusammenhang mit dem Prog. :wink:

Ich halte mich auch nicht an diesen sogenanten "Standard", hab mir ein eigenes System zur Namensvergabe im laufe der Jahre angeeignet.

choose 23. Dez 2003 17:04

Re: Array an procedure übergeben
 
Zitat:

Zitat von himitsu
Die Namen sind Delphi total egal.

Das ist mir bewusst, himitsu. Bis auf wenige Ausnahmen (zB Prozedur Register zum Registrieren von Komponenten) muss man bei Delphi auch nicht auf Groß-/Kleinschreibung achten.

Zitat:

Zitat von himitsu
Diese "Vorgaben" für die Namensvergabe [..] ist nur zum einfachen lesen/verständnis der Quellcodes gedacht [..].

Und genau das ist der Punkt: Der Grund, warum man häufig zur Hochsprache greift ist eben die bessere Verständlichkeit der (fremden) Quellen . Das Resultat hätte man auch in ASM oder gar mit puren Opcodes realisieren können. Die "Quelle, von der ich das nabe" heißt im übrigen VCL/CLX und schuf eine gewisse Einstellung zu Bedeutungen von Bezeichnern.
Oder würdest Du hinter EConvertError eine Klasse zur Darstellung von Schachfiguren erwarten, deren Dartellungsmethode sinnigerweise Create heißt? Technisch machbar.

Zitat:

Zitat von himitsu
Und das was Igotcha da geschrieben hat, sind mit Sicherheit nur Beispiele und sehen nicht im direkten Zusammenhang mit dem Prog. :wink:

Und da war ich eben nicht ganz so sicher, gut dass Du mich in dieser Hinsicht beruhigt hast ;)

Igotcha 28. Dez 2003 00:23

Re: Array an procedure übergeben
 
Zitat:

Zitat von himitsu
Delphi hat mit zwar gleichen Typendeklaration einige Progleme.

Das beschriebene Problem konnte ich ja nun mittlerweile lösen, jetzt tritt für mich aber erneut ein (wahrscheinlich) ähnlich geartetes Problem auf - sind meine ersten Versuche mit Klassen und Objekten:

Delphi-Quellcode:
unit AKarten;
// Klasse der Aktionskarten
interface
uses DXDraws, DXClass,DXSprite, SysUtils, EKarten;

Type TACard = class(TImageSpriteEx)
// Felder
private
    fname: String;       // Kartenname;
    fed: String;         // Kürzel der Edition, z.B. 'WC'
    fnummer: String;    // Nummer der Karte, z.B. 39
    fcid : integer;       // lfd. Nummer im Stapel
    fcowner: integer;     // Spieler, der die Karte besitzt
  // Methoden
    function getName: String;
    procedure setName(Name: String);
    function getED: String;
    procedure setED(Edition: String);
    function getNummer: String;
    procedure setNummer(Nummer: String);
    function getCID: integer;
    procedure setCID(CID: integer);
    function getCOwner: integer;
    procedure setCOwner(COwner: integer);
public
    property Name: string read getName write setName;
    property Edition: string read getED write setED;
    property Nummer: string read getNummer write setNummer;
    property CID: integer read getCID write setCID;
    property COwner: integer read getCOwner write setCOwner;
 
    procedure DoMove(MoveCount: Integer);override;
    procedure DoCollision(Sprite: TSprite; var Done: Boolean);override;

    procedure LoadECard(Imagelist: TDXImageList); // Lädt das Bild der Karte
end;

implementation
...
procedure TACard.LoadECard(ImageList: TDXImageList);
var
  ix: integer;
  strCName: String;
  bImGFound: Boolean;
begin
    bImgFound:=false;
    strCname:=fed+fnummer;
    for ix:=0 to Imagelist.Items.Count-1 do
    begin
        if Imagelist.Items.Items[ix].Name=strCName then
        begin
          bImgFound:=true;
          Break;
        end;
    end;
    if bIMgFound=false then
    begin
      ImageList.Items.Add;
      with ImageList.Items[ImageList.Items.Count-1] do
      begin
      Picture.LoadFromFile (MYPFAD+fed+'\small\'+fnummer+'.jpg');
      fname:=strCName;
      Name := fname;
      PatternWidth := 0;
      PatternHeight := 0;
      SkipHeight := 0;
      SkipWidth := 0;
      SystemMemory := False;
      //Transparent := Transp;
      //TransparentColor := TranspColor;
      Restore;
      end;
    end;
    Image:=Imagelist.Items.Find(strCName);
end;
In der Game-Unit ist deklariert

Delphi-Quellcode:
type ADummy = array of TACard;
und

Delphi-Quellcode:
ADeck1, AADeck1: ADummy;
Erstellt werden die ADeck1-Objekte in einer Schleife mit:

Delphi-Quellcode:
inc(iA);
        SetLength(ADeck1,iA);
        ADeck1[iA-1]:=TACard.Create(frmMain.DXSpriteEngine1.Engine);
        ADeck1[iA-1].Edition:=strLeft(S,2);
        ADeck1[iA-1].Nummer:=strRight(S,Length(S)-2);
        ADeck1[iA-1].CID:=iA-1;
        ADeck1[iA-1].COwner:=0;
        ADeck1[iA-1].LoadECard(frmMain.DXCards);
        ADeck1[iA-1].Height:=127;
        ADeck1[iA-1].Width:=90;
        ADeck1[iA-1].X:=200+(iA*20);
        ADeck1[iA-1].Y:=250;
Das Mischen der Karten funktioniert mit Eurer Hilfe nun super mit:

Delphi-Quellcode:
function MixACards(Var AParam: ADummy): ADummy;
var
  CDummy: TACard;
  ix, ir: integer;
begin
  SetLength(Result, Length(AParam));
  for ix:=0 to High(AParam) do
  begin
    ir:=Random(High(AParam));
    CDummy:=Aparam[ix];
    AParam[ix]:=AParam[ir];
    AParam[ir]:=CDummy;
  end;
end;
Wenn in der Mischroutine

Delphi-Quellcode:
AParam[ix]:=AParam[ir];
funktioniert, warum klappt dann dies nicht?

Delphi-Quellcode:
Setlength(AADeck1,1);
  AADeck1[0]:=TACard.Create(frmMain.DXSpriteEngine1.Engine);
  AADeck1[0]:=ADeck1[High(ADeck1)];
Der Compilerlauf ist fehlerfrei, jedoch bricht das Programm mit einem "Access-Violation" beim "Draw" der SpriteEngine ab. Kommentiere ich die Drei Zeilen aus, gibt es keine Probleme.

Sorry, wenn das Ganze nun etwas länger geworden ist, aber ich bin ja lernwillig ;-)


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:56 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz