Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Stack Overflow - Dynamische Arrays (https://www.delphipraxis.net/168076-stack-overflow-dynamische-arrays.html)

roboter202 3. Mai 2012 21:36

Stack Overflow - Dynamische Arrays
 
Hi,


Ich generiere ein Labyrinth mit einer rekursiven Prozedur.



ich hab den Code:

Delphi-Quellcode:
procedure TWorld.generate(_x, _y: Integer);
var
  neighbours: array of TVect2i;
  r: ShortInt;
begin
  //list of unvisited neighbours
  if (_y <> 0) then
  begin
    if (cellMap[_x, _y -1] = false) then //TOP
    begin
      SetLength(neighbours, Length(neighbours) +1);
      neighbours[high(neighbours)].x := _x;
      neighbours[high(neighbours)].x := _y -1;
    end;
  end;

  if (_x <> 0) then
  begin
    if (cellMap[_x -1, _y] = false) then //LEFT
    begin
      SetLength(neighbours, Length(neighbours) +1);
      neighbours[high(neighbours)].x := _x -1;
      neighbours[high(neighbours)].x := _y ;
    end;
  end;

  if (_y <> height -1) then
  begin
    if (cellMap[_x, _y +1] = false) then //Bottom
    begin
      SetLength(neighbours, Length(neighbours) +1);
      neighbours[high(neighbours)].x := _x ;
      neighbours[high(neighbours)].x := _y +1;
    end;
  end;

  if (_x <> width -1) then
  begin
    if (cellMap[_x +1, _y] = false) then //RIGHT
    begin
      SetLength(neighbours, Length(neighbours) +1);
      neighbours[high(neighbours)].x := _x +1;
      neighbours[high(neighbours)].x := _y ;
    end;
  end;
  //

  if not cellMap[_x, _y] then //Was this cell vistited?
  begin
    //Mark as visited
    cellMap[_x, _y] := true;
    if Length(neighbours) > 1 then //Can I go on with other paths here?
    begin
      //Move to Stack
      setLength(cellStack, Length(cellStack) +1);
      cellStack[high(cellStack)].x := _x;
      cellStack[high(cellStack)].x := _y;
    end;
  end;


  if Length(neighbours) > 0 then
  begin
    //Pick a random neighbour
    r := Random(Length(neighbours));
    //Remove Wall
    if neighbours[r].x > _x then
    begin
      //Right
      wallMap[_x, _y, 1] := true;
    end else
    if neighbours[r].x < _x then
    begin
      //Left
      wallMap[_x -1, _y, 1] := true;
    end else
    if neighbours[r].y > _y then
    begin
      //Bottom
      wallMap[_x, _y, 0] := true;
    end else
    if neighbours[r].y < _y then
    begin
      //Top
      wallMap[_x, _y -1, 0] := true;
    end;
    generate(neighbours[r].x, neighbours[r].y);

  end else
  begin
    if stackPos < high(cellStack) then
    begin
      stackPos := stackPos +1;
      generate(cellStack[stackPos].x, cellStack[stackPos].y)
    end;
  end;
end;
und was auch noch wichtig sein könnte ist


Delphi-Quellcode:
     
cellMap: array of array of Boolean;
wallMap: array of array of array [0..1] of Boolean; //0 => Horizontal; 1 => Vertical; X,Y of Cell to Left Top
cellStack: array of TVect2i;
und

Delphi-Quellcode:
 
TVect2i = record
    x,y: Integer;
  end;
Jetzt bekomme ich wenn ich width und height auf 100 setze einen Stack Overflow. Warum ich hab gelesen das es bei einem rekursiven Prozeduraufruf passieren kann. (Hab ich ja) aber was kann ich denn jetzt tun. Muss ich das Zeug was die Prozedur braucht auf einen dynamischen Array schmeißen oder geht das auch anders?

Gruß roboter202

Delphi-Laie 3. Mai 2012 22:00

AW: Stack Overflow - Dynamische Arrays
 
Stack overflow kommt daher, daß die Rekursion nicht abbricht, sondern sich irgendwo in einer Endlosschleife verfängt. Dieser Endlosigkeit setzt die Endlichkeit des Stack(speicher)s jedoch irgendwann ein Ende.

himitsu 3. Mai 2012 22:53

AW: Stack Overflow - Dynamische Arrays
 
Es währe auch zu einfach, wenn alle Programmierer wüßten was ein Debugger ist und wie man den verwendet.
Und ja, selbst Delphi 7 kennt einen Stack-Trace (Aufruf-Stack).

Popov 4. Mai 2012 00:34

AW: Stack Overflow - Dynamische Arrays
 
Ich hab auch irgendwann ein Labyrinth geprogt und es auch rekursiv berechnet. Ob ich es 20x20 oder 500x500 mache, es funktioniert ohne Fehlermeldung. Die Größe dürfte also nicht das Problem sein. Ich tippe drauf, dass es irgendwo eine lost in space Geschichte wird.

Furtbichler 4. Mai 2012 06:02

AW: Stack Overflow - Dynamische Arrays
 
Rekursiv <> Rekursiv.
Hier wird für jeden Nachbarn die Routine rekursiv aufgerufen, was bei einem 100x100 Feld entsprechend viele Aufrufe bedeuten könnte.

Da es sich um eine Rechtsrekursion handelt, kann diese bedenkenlos in eine Iteration umgewandelt werden, ohne Gehirnwindungskrämpfe zu bekommen.

roboter202 4. Mai 2012 13:05

AW: Stack Overflow - Dynamische Arrays
 
Zitat:

Zitat von Delphi-Laie (Beitrag 1164779)
Stack overflow kommt daher, daß die Rekursion nicht abbricht, sondern sich irgendwo in einer Endlosschleife verfängt. Dieser Endlosigkeit setzt die Endlichkeit des Stack(speicher)s jedoch irgendwann ein Ende.

Nein das stimmt nicht irgendwann gibt es keine Zellen ohne Nachbarn mehr

Code:
Rekursiv <> Rekursiv.
Hier wird für jeden Nachbarn die Routine rekursiv aufgerufen, was bei einem 100x100 Feld entsprechend viele Aufrufe bedeuten könnte.

Da es sich um eine Rechtsrekursion handelt, kann diese bedenkenlos in eine Iteration umgewandelt werden, ohne Gehirnwindungskrämpfe zu bekommen.
Stimmt wenn ich einen while-Schleife nehme und den Code etwas modifiziere dann müsst das auch gehen. Da bin heute morgen auch drauf gekommen.

DANKE!!! :angel:


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