Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Zugriffsverletzung?? (https://www.delphipraxis.net/160025-zugriffsverletzung.html)

Michelle 23. Apr 2011 18:01

Zugriffsverletzung??
 
Hallo!

Ich habe ein Problem. Ich programmiere gerade ein Spiel, in dem eine Spielfigur Sterne einsammeln muss. Für die Sterne habe ich eine Klasse aufgemacht: TStar.

Code:
TStar = class
  Found : Boolean;
  PosX, PosY : integer;
  procedure Shine;

...

var
  Star : Array[1..20] of TStar; //es gibt in jedem Level 20 Sterne
Wenn das Level lädt möchte ich jedem Stern seine Position zuweisen (PosX und PosY), die im Memo-Feld MemoLoadPos steht.

Code:
Star[1].PosX := StrToInt(MemoLoadPos.Lines[2]);
Star[1].PosY := StrToInt(MemoLoadPos.Lines[3]);
Delphi sagt, das sei eine Zugriffsverletzung, aber ich bin mir nicht bewusst, irgendjemanden verletzt zu haben.

Vielen Dank im Voraus für eure Antworten! Ich hoffe, die Frage ist nicht zu dämlich, aber ich habe echt keine Ahnung!

mkinzler 23. Apr 2011 18:04

AW: Zugriffsverletzung??
 
Wieviel Zeilen hat das Memo? (.Lines ist 0-indiziert)

Michelle 23. Apr 2011 18:07

AW: Zugriffsverletzung??
 
Das Memo-Feld hat 22 Zeilen. Vorher lade ich eine txt-Datei in das Memo-Feld, in dem die Positionen der Spielfigur und der Sterne stehen.

mkinzler 23. Apr 2011 18:10

AW: Zugriffsverletzung??
 
Hast du die Instanzen der Klasse auch erzeugt?

Delphi-Quellcode:
Star[1] := TStar.Create;

Michelle 23. Apr 2011 18:19

AW: Zugriffsverletzung??
 
Das habe ich auch schon versucht. Ich rufe die Prozedure StarCreate in FormCreate auf
Ich habe eine Prozedur "FormCreate", während der ich die Prozedur StarCreate aufrufe. (In StarCreate macht er die Instanzen

Code:
procedure TFormLvl.StarCreate;
var i : integer;
begin
  for i := 1 to 20 do Star[i].Create;
  Star[1].PosX := ... //wie oben beschrieben

  ImgStar1.Left := Star[1].PosX;
  ImgStag1.Top := Star[1].PosY;
end;

Wie gesagt rufe ich die Prozedur in procedure FormCreate auf. Das macht er auch alles, aber die nächste ZEile im FormCreate wird als Fehler angezeigt. Dabei ist es egal, welche Zeile als nächstes im FormCreate steht. Delphi meldet immer noch eine Zugriffsverletzung und die nächste Zeile wird blau hinterlegt.

mkinzler 23. Apr 2011 18:22

AW: Zugriffsverletzung??
 
Füge mal begin..end ein
Delphi-Quellcode:
for i := 1 to 20 do Star[i].Create;
begin
  Star[1].PosX := ... //wie oben beschrieben

  ImgStar1.Left := Star[1].PosX
  ImgStag1.Top := Star[1].PosY;
end;

Michelle 23. Apr 2011 18:29

AW: Zugriffsverletzung??
 
Aber ich will doch nur das Star[i].Create 20 mal wiederholen. Das andere tipp ich 20 mal ein, weil ich ja jedes einzelne Bild verschieben will und ich keinen Array of Image habe sondern nur 20 einzelne Bilder ImgStar1, ImgStar2, ... Außerdem verwirrt mich diese komische Zugriffsverletzung. Delphi hat irgendein Problem mit meinem TStar bzw. den Instanzen Star[i]. Ich habe schon viel mit denen probiert aber immer gab es eine Zugriffsverletzung. Habe ich vielleicht im Aufbau etwas falsch gemacht oder muss man bei dem Create irgendetwas beachten?

mkinzler 23. Apr 2011 18:32

AW: Zugriffsverletzung??
 
Ist das Memo zu dieser Zeit schon gefüllt?

Michelle 23. Apr 2011 18:36

AW: Zugriffsverletzung??
 
Ja, ist es. Zu dem Zeitpunkt stehen 22 verschiedene ganzzahlige Werte im MemoFeld.

mkinzler 23. Apr 2011 18:38

AW: Zugriffsverletzung??
 
Poste mal den ganzen Quelltext

Zibelas 23. Apr 2011 18:41

AW: Zugriffsverletzung??
 
Hmm, also was mich wundert ist folgendes:

Du hast 22 Zeilen in der Memo und willst 20 Sterne erzeugen.
Star[1].PosX := StrToInt(MemoLoadPos.Lines[2]);
Star[1].PosY := StrToInt(MemoLoadPos.Lines[3]);

Müssten dir da nicht die Zeilen ausgehen? Versuch den Pos fixe Werte erstmal zuzuweisen, es könnte ja auch sein, dass die Einträge in der Memo sich nicht in einen Integer konvertieren lassen. (Da ich die Einträge nicht sehen kann nur ne Vermutung)

Code:
    Star[1].PosX := 10;
    Star[1].PosY := 10;

Sir Rufo 23. Apr 2011 18:45

AW: Zugriffsverletzung??
 
Zitat:

Zitat von mkinzler (Beitrag 1096657)
Füge mal begin..end ein
Delphi-Quellcode:
for i := 1 to 20 do Star[i].Create;
begin
  Star[1].PosX := ... //wie oben beschrieben

  ImgStar1.Left := Star[1].PosX
  ImgStag1.Top := Star[1].PosY;
end;

So wird aber keine Instanz erzeugt, sondern einfach nur der Constructor (verhält sich hierbei wie ein Methode) einer nicht instantierten Klasse.
Delphi-Quellcode:
foo := TFoo.Create;
Somit in diesem Beispiel bitte
Delphi-Quellcode:
for i := 1 to 20 do
  Star[ i ] := TStar.Create;

himitsu 23. Apr 2011 18:51

AW: Zugriffsverletzung??
 
Zitat:

Zitat von mkinzler (Beitrag 1096657)
Füge mal begin..end ein
Delphi-Quellcode:
for i := 1 to 20 do Star[i].Create;
begin
  Star[1].PosX := ... //wie oben beschrieben

  ImgStar1.Left := Star[1].PosX
  ImgStag1.Top := Star[1].PosY;
end;

Das BEGIN natürlich noch vor das Create (und natürlich mit der richtigen Variante des Create)

Delphi-Quellcode:
for i := 1 to 20 do
begin
  Star[i] := TStar.Create;
  Star[i].PosX := ...
Ansonsten kann es nicht schaden, wenn du in den Projektoptionen mal die Überlauf- und die Bereichsprüfung aktivierst.

Michelle 23. Apr 2011 19:11

AW: Zugriffsverletzung??
 
Code:

type
  TFormLvl = class(TForm)
    {}
  end;

  TSpielfigur = class
    {}
  end;


  TStar = class
    Found     : Boolean;
    PosX, PosY : integer;
    procedure Shine;
    procedure Find;
    procedure Fly;


  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  FormLvl                                 : TFormLvl;
  Spielfigur                              : TSpielfigur;
  Star                                    : Array[1..20] of TStar;
  MoveRight, MoveLeft, Fall               : Boolean;
  JumpCount, SpLeft, SpTop, SpStartX, SpStartY : integer;


implementation

{$R *.dfm}

procedure TFormLvl.StarCreate3;
var i : integer;
begin
  MemoLoadPos.Lines.LoadFromFile('..\Level\1\Pos.txt');
 
  for i := 1 to 20 do Star[i].Create;

  Star[1].PosX := StrToInt(MemoLoadPos.Lines[2]);
  Star[1].PosY := StrToInt(MemoLoadPos.Lines[3]);

  Star[2].PosX := StrToInt(FormLvl.MemoLoadPos.Lines[4]);
  Star[2].PosY := StrToInt(FormLvl.MemoLoadPos.Lines[5]);

  Star[3].PosX := StrToInt(FormLvl.MemoLoadPos.Lines[6]);
  Star[3].PosY := StrToInt(FormLvl.MemoLoadPos.Lines[7]);

  Star[4].PosX := StrToInt(FormLvl.MemoLoadPos.Lines[8]);
  Star[4].PosY := StrToInt(FormLvl.MemoLoadPos.Lines[9]);

  Star[5].PosX := StrToInt(FormLvl.MemoLoadPos.Lines[10]);
  Star[5].PosY := StrToInt(FormLvl.MemoLoadPos.Lines[11]);

  Star[6].PosX := StrToInt(FormLvl.MemoLoadPos.Lines[12]);
  Star[6].PosY := StrToInt(FormLvl.MemoLoadPos.Lines[13]);

  ImgStar1_1.Left := Star[1].PosX;
  ImgStar1_1.Top := Star[1].PosY;
end;

procedure TFormLvl.FormCreate(Sender: TObject);
begin
  DoubleBuffered := true;
  MediaPlayer1.Play;

  Spielfigur.BorderLoad;
  StarCreate3;    
 
  Spielfigur.Move; //hier wird der Fehler angezeigt

  SpLeft := SpStartX; // MLeft und MTop sind die aktuellen Koordinaten der Spielfigur,
  SpTop := SpStartY; // MStartX und MStartY sind die Startkoordinaten am Anfang des Spiels
end;

procedure TSpielfigur.Move;
begin
  if MoveRight then SpLeft := SpLeft + 10; //MoveRight und MoveLeft werden auf den Cursortasten
  if MoveLeft then SpLeft := SpLeft - 10; // true oder false gesetzt. Hat noch nie Probleme
end;

Sir Rufo 23. Apr 2011 19:11

AW: Zugriffsverletzung??
 
Zitat:

Zitat von Michelle (Beitrag 1096658)
Aber ich will doch nur das Star[i].Create 20 mal wiederholen. Das andere tipp ich 20 mal ein, weil ich ja jedes einzelne Bild verschieben will und ich keinen Array of Image habe sondern nur 20 einzelne Bilder ImgStar1, ImgStar2, ...

Darum erübrigt sich das mit dem
Delphi-Quellcode:
begin ... end
Es lag halt nur ein Fehler in der Instanzerzeugung vor :)

Hmmm ... der Fehler ist immer noch in dem Quellcode
Delphi-Quellcode:
Star[ i ].Create;
Ändern auf
Delphi-Quellcode:
Star[ i ] := TStar.Create;

Michelle 23. Apr 2011 19:18

AW: Zugriffsverletzung??
 
WAHNSINN - ES KLAPPT!!!!!! Vielen, vielen Dank für eure Hilfe!
Der Fehler lag wirklich bei dem
Code:
Star[i].Create;
. Stattdessen
Code:
Star[i] := TStar.Create
und es funktioniert!!!
Ihr habt mein Ostern gerettet! 1000 Dank!!

Zibelas 23. Apr 2011 19:23

AW: Zugriffsverletzung??
 
Noch ein Vorschlag zur Optimierung wo du dir später viel Arbeit sparen wirst:

Zitat:

Das andere tipp ich 20 mal ein, weil ich ja jedes einzelne Bild verschieben will und ich keinen Array of Image habe sondern nur 20 einzelne Bilder ImgStar1, ImgStar2
Nutz
Delphi-Quellcode:
findcomponent
Code:
TImage(findcomponent('ImgStar'+inttostr(i))).left := Star[i].PosX;
Du kannst in einer Schleife alle Zuweisungen machen, bist nicht von der Anzahl der Sterne in einem Level abhängig (also kann ein Level auch mal mehr oder weniger Sterne haben)

Die ImgStar Bilder kannst du natürlich auch zur Laufzeit erzeugen. So bleibt dein Spiel dynamisch und ein neues Level kann über die Ladefile erstellt werden, auch wenns mehr als 20 Sterne sind.

mkinzler 23. Apr 2011 19:29

AW: Zugriffsverletzung??
 
Oder noch besser packe diese auch in einen Array oder eine Liste oder verwende eine Imageliste

Michelle 23. Apr 2011 19:31

AW: Zugriffsverletzung??
 
Wow, super Tipp, vielen Dank! Davon habe ich noch nie gehört, aber das ist wirklich eine viel bessere Lösung!!
Denkst du, man kann aus dem Rest auch eine Schleife machen?

Code:
 
  Star[1].PosX := StrToInt(MemoLoadPos.Lines[2]);
  Star[1].PosY := StrToInt(MemoLoadPos.Lines[3]);

  Star[2].PosX := StrToInt(MemoLoadPos.Lines[4]);
  Star[2].PosY := StrToInt(MemoLoadPos.Lines[5]);

  Star[3].PosX := StrToInt(MemoLoadPos.Lines[6]);
  Star[3].PosY := StrToInt(MemoLoadPos.Lines[7]);

  ...
Star[i].PosX müsste von 1 bis 20 gehen, MemoLoadPos.Lines[i] von 2 bis 42. Geht das?

Ralf Kaiser 23. Apr 2011 19:36

AW: Zugriffsverletzung??
 
Zitat:

Zitat von Michelle (Beitrag 1096656)
Ich habe eine Prozedur "FormCreate", während der ich die Prozedur StarCreate aufrufe. (In StarCreate macht er die Instanzen

Code:
procedure TFormLvl.StarCreate;
var i : integer;
begin
  for i := 1 to 20 do Star[i].Create;
  Star[1].PosX := ... //wie oben beschrieben

  ImgStar1.Left := Star[1].PosX;
  ImgStag1.Top := Star[1].PosY;
end;

Du musst das Ergebnis, das der Constructor liefert in dem Array speichern und nicht nur einfach den Constructor aufrufen:

Delphi-Quellcode:
for i := 1 to 20 do Star[i] := TStar.Create; // <==
Star[1].PosX := ...
Ciao,
Ralf

himitsu 23. Apr 2011 19:39

AW: Zugriffsverletzung??
 
Delphi-Quellcode:
for i := 1 to 20 do
begin
  Star[i] := TStart.Create; // man könnte sich glatt fragen, wie du den mehrfachen Hinweis mehrer Leute überlesen konntest
  Star[i].PosX := StrToInt(MemoLoadPos.Lines[i * 2]);
  Star[i].PosY := StrToInt(MemoLoadPos.Lines[i * 2 + 1]);
end;
bzw., da nur die ersten 6 befüllt werden
Delphi-Quellcode:
for i := 1 to 20 do
  Star[i] := TStart.Create;
for i := 1 to 6 do
begin
  Star[i].PosX := StrToInt(MemoLoadPos.Lines[i * 2]);
  Star[i].PosY := StrToInt(MemoLoadPos.Lines[i * 2 + 1]);
end;

Zibelas 23. Apr 2011 19:41

AW: Zugriffsverletzung??
 
das war himitsu schneller als ich^^

Grundsätzlich kann man alles in einer Schleife abarbeiten, wenn der Code sehr ähnlich ist.

Michelle 23. Apr 2011 20:06

AW: Zugriffsverletzung??
 
Wow, ihr habt meine über 100 Zeilen gerade auf 5 reduziert :) Ich muss wohl noch eine Menge lernen, wenn es ums Programmieren geht! Vielen, vielen Dank nochmal für eure kompetente, schnelle und freundliche Hilfe!!!

Sir Rufo 23. Apr 2011 20:38

AW: Zugriffsverletzung??
 
Zitat:

Zitat von Michelle (Beitrag 1096680)
Wow, ihr habt meine über 100 Zeilen gerade auf 5 reduziert :) Ich muss wohl noch eine Menge lernen, wenn es ums Programmieren geht! Vielen, vielen Dank nochmal für eure kompetente, schnelle und freundliche Hilfe!!!

Beim Programmieren gibt es u.a. eine Regel die da abgekürzt lautet DRY = Don't Repeat Yourself

Immer dann, wenn man sich wiederholt, kann man es besser schreiben ;)

Jumpy 26. Apr 2011 09:56

AW: Zugriffsverletzung??
 
Zitat:

Zitat von Michelle (Beitrag 1096674)
Wow, super Tipp, vielen Dank! Davon habe ich noch nie gehört, aber das ist wirklich eine viel bessere Lösung!!
Denkst du, man kann aus dem Rest auch eine Schleife machen?

Code:
 
  Star[1].PosX := StrToInt(MemoLoadPos.Lines[2]);
  Star[1].PosY := StrToInt(MemoLoadPos.Lines[3]);

  Star[2].PosX := StrToInt(MemoLoadPos.Lines[4]);
  Star[2].PosY := StrToInt(MemoLoadPos.Lines[5]);

  Star[3].PosX := StrToInt(MemoLoadPos.Lines[6]);
  Star[3].PosY := StrToInt(MemoLoadPos.Lines[7]);

  ...
Star[i].PosX müsste von 1 bis 20 gehen, MemoLoadPos.Lines[i] von 2 bis 42. Geht das?


In einer Schleife von i:=1 bis 20:
Delphi-Quellcode:
  Star[i].PosX := StrToInt(MemoLoadPos.Lines[2*i]);
  Star[i].PosY := StrToInt(MemoLoadPos.Lines[2*i+1]);


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:03 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