Autor Beitrag
knittel
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: Mo 02.08.10 17:34 
Hallo allerseits,
ich bin neu hier und habe ein problem bei einem Array, bin noch ein blutiger Anfänger.

Ich entwickle gerade ein Spiel bei dem man seine Einheiten rundenbasiert steuert. Die Einheiten können Minen legen. Sobald ein Gegner in einen Bereich um die Mine mit dem Abstand 24 kommt, soll die Mine explodieren und alle Gegner darin Schaden erhalten.

Danach soll logischerweise die Mine verschwinden und das Array soll entsprechend gekürzt werden.

Ich habe folgenden Code dafür.
ausblenden 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:
// Mine Explode?
procedure MineActive ();
var i, j, a: integer;
begin
a:=0// Anzahl um wie viel das Array verkürzt werden soll
for i:= 0 To High(ShapePlayerMines) do
begin
 if (ShapePlayerMines[i].Visible = false) then
// Sobald ein Gegner in den Bereich um die Mine läuft setzte ich 
// Visible, der Mine auf false;
 begin
  a:=a+1// Das Array soll um 1 mehr verkürzt werden.
  ShapePlayerMines[i].Free; // Die Mine wird gelöscht
  for j:= i to (High(ShapePlayerMines)-1do 
// Alle Minen danach sollen nach vorne verschoben werden.
  begin
   ShapePlayerMines[j]:=ShapePlayerMines[j+1];
  end;
 end;
end;
// Ich kürze die Länge des Array um die Anzahl der explodierten Minen.
SetLength(ShapePlayerMines,(Length(ShapePlayerMines)-a));
end// of procedure


Die procedure, in der das Betreten der Mine überprüft wird.
ausblenden 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:
procedure CheckCPUandLifeOfPlayerUnits ();
var i, a, Amount: integer;
begin

// ... Ich habe hier etwas Code entfernt welcher für einen anderen Teil
// des Spiels zuständig ist.

// Look For Mines
for i:= 0 To High(ShapePlayerMines) do // Alle Minen werden überprüft
begin
 for a:= 0 To High(ShapeEnemies) do // Alle Gegner werden überprüft
 begin
  if ((ShapeEnemies[a].Left > ShapePlayerMines[i].Left - 24AND
      (ShapeEnemies[a].Left < ShapePlayerMines[i].Left + 26AND
      (ShapeEnemies[a].Top > ShapePlayerMines[i].Top - 24AND
      (ShapeEnemies[a].Top < ShapePlayerMines[i].Top + 26)) then
   // if ist true wenn sich der Gegner innerhalb des Bereiches befindet.
   begin
   ShapePlayerMines[i].Visible:=false; // Um sie später in MineActive zu zerstören
   EnemyBots[a, 2]:=EnemyBots[a, 2] - 1
   // EnemyBots[a,2] entspricht dem Leben des Gegners
   CheckEnemyAlive (StrToInt(ShapePlayerMines[i].Hint)); 
   // Überprüft ob der Gegner noch lebt 
   // In ShapePlayerMines[i].Hint steht der Index der Einheit, welche die Mine gelegt hat
   // Diese Einheit erhält Erfahrungspunkte.
   end;
 end// of for
end// of for
MineActive (); // siehe procedure oben
end// of procedure


Das Spiel funktioniert sehr lange gut. Irgendwann mal nachdem etwa 12 oder 13 Minen explodiert sind kommt plötzlich folgende Fehlermeldung:

'Access Violation at 00007469'

Danke im voraus. :)
Teekeks
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 211
Erhaltene Danke: 23



BeitragVerfasst: Mo 02.08.10 18:04 
Bist du dir denn sicher das du auch diese ganzen Klassen in dem Array Initialisiert hast?
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Mo 02.08.10 20:07 
das problem ist eher:
du zählst alle minen durch
löschst eine in der mitte und verschiebst alle danach
ABER zählst bis zur letzten durch
-->bei 1 gelöschten ist die letzte=vorletzte und wird 2 mal geprüft.
angenommen du "free"st diese vorletzte und prüfst dann die letzte --> AV

Lösung: äußere schleife eine while schleife mit variablen oberen zähler (nämlich "Length(ShapePlayerMines)-a") und die innere for schleife mit "Length(ShapePlayerMines)-a-1" als obere schranke

Für diesen Beitrag haben gedankt: knittel
Xion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
Beiträge: 1952
Erhaltene Danke: 128

Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
BeitragVerfasst: Mo 02.08.10 20:16 
user profile iconknittel hat folgendes geschrieben Zum zitierten Posting springen:

Das Spiel funktioniert sehr lange gut. Irgendwann mal nachdem etwa 12 oder 13 Minen explodiert sind kommt plötzlich folgende Fehlermeldung:

'Access Violation at 00007469'


Zum Hintergrund bisschen was:
Access Violation heißt immer du schreibst/liest wo rum wo du nicht darfst. Dafür kriegst du auf die Finger. Dass das erst irgendwann auftritt (und nicht schon beim ersten mal) ist ne ziemlich gemeine Sache. Es kann sogar so sein dass es erst nach ner Woche mal zum Fehler kommt wenn du grad wo anders rumbastelst. Vorher hast du wohl nie einen verbotenen Bereich erwischt und sonst irgendwo rumgelesen, was aber niemanden gestört hat. Das tolle an dem Fehler ist, dass du oft weder von Delphi gesagt bekommst wo der Fehler aufgetreten ist, die Fehlermeldung absolut nichtssagen ist und eben nicht immer erscheint.

_________________
a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Mo 02.08.10 22:51 
nicht ganz. mit dem delphi-debugger und der call-history kann man die stelle ganz gut finden bzw. eingrenzen.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 03.08.10 00:28 
Zudem kann man mittels Mapfile und CPU-Fenster auch mit der Speicherstelle ggf. etwas anfangen. Wenn die sehr klein ist (0 oder 10 z.B.), hat man meistens irgendein nicht initialisiertes Objekt. Denn dann wird der Offset der entsprechenden Speicherstelle zu der des Objekts addiert und das ist ja dann 0.

Es ist zwar aber nicht ganz trivial mit den Informationen etwas anzufangen, aber entweder mit dem genannten Debugger und Call Stack oder auch mit MadExcept, Eurekalog oder JclDebug lässt sich da viel herausfinden.
knittel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: Di 03.08.10 10:32 
Danke erstmal für alle die etwas geschrieben haben.
Ich habe Flamefire's Lösung benutzt und mittlerweile funktioniert's. Ich habe es auch auf die Gegner übertragen, die ja auch sterben können.

Danke nochmals. :)

_________________
"Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."