Seite 1 von 1

Procedure in Procedure Extrem häufig aufrufen

Verfasst: 12.04.2011 18:17
von FosJonas
Guten tag,

wenn ich die Procedure A() in der Procedure A() aufrufe gibt das im Prinzip ja eine endlosschleife:

Code: Alles auswählen

Procedure A()
  A()
EndProcedure
A()
Das Problem ist nun das nach groben 16700 durchläufen das ganze abstürtzt ( das zu debuggende exe ...). Was ja auch ganz gut ist damit es eben keine endlosschleife gibt, nur in meinem fall muss es eben weit über diese Grenze hinausgehen.
Gibt es eine Möglichkeit das ganze zu deaktivieren? (also das automatische beenden)

Danke im vorraus.

Re: Procedure in Procedure Extrem häufig aufrufen

Verfasst: 12.04.2011 18:30
von RSBasic
Warum soll die Prozedur sich unendlich öffnen? Was für einen Sinn macht es denn? Was willst du denn überhaupt machen? Willst du einen bestimmten Vorgang unendlich wiederholen (Z.B. bei einer Überprüfung)? Das kannst du in der Prozedur auch mit Repeat : Until/Forever realisieren.

Re: Procedure in Procedure Extrem häufig aufrufen

Verfasst: 12.04.2011 18:33
von STARGÅTE
Nein, das ist ganz einfach ein Stapelüberlauf.

Mit jedem Prozedur-Aufruf erzeugst du ja eine Art Umgebung (für Variablen und Rückgabewerte) und da gibt es nun mal eine Grenze!

Das ist keine For-To-Schleife, wenn du es als eine solche missbrauchst, bist du selbst Schult.
Dann ist dein Ansatz vüllig falsch, vorallem wenn du weit mehr rekursive aufrufe brauchs als ca 16700 ...

Re: Procedure in Procedure Extrem häufig aufrufen

Verfasst: 12.04.2011 18:39
von NicTheQuick
Außerdem sei noch dazu gesagt, dass man jede rekursive Funktion auch iterativ machen kann.

Re: Procedure in Procedure Extrem häufig aufrufen

Verfasst: 12.04.2011 18:47
von FosJonas
@RSBasic
Das ganze geht nur extrem oft, nicht unendlich es geht dabei um das erstellen einer Heightmap:

Code: Alles auswählen

Procedure GetArroundHeight(X.i,Z.i,Height.i)
  Protected AX.i,AZ.i,RX.i,RZ.i
  RandomSeed(ElapsedMilliseconds())  
  For AX = -1 To 1
    For AZ = -1 To 1
      RX = GetHeightX(X+AX)
      RZ = GetHeightZ(Z+AZ)
      If RX >= 0 And RZ >= 0
        If Map_Height(RX,RZ) = 0
          Map_Height(RX,RZ) = Height + Random(5)-5          
          GetArroundHeight(RX,RZ,Height + Random(5)-5)               
        EndIf
      EndIf
    Next
  Next  
EndProcedure
Die Proceduren GetHeight geben nur die Absolute Position in der Karte zurück (meine Karte hat im Prinzip keine ecken) sind also nicht weiter wichtig.

@Stargate
Hmm gut dann muss ich das wohl anders lösen, habe die Methode in einem Code irgendwo hier im Forum aufgefangen. Leider habe ich keine Ahnung wie ich das ganze mit einer For Schleife lösen könnte.

@Nic
Den Begriff "Iterativ" musste ich erstmal in Wiki eingeben Oo. Hmm so wie ich das verstehe würde das mein Problem lösen und beschleunigen? Wie nutzt man den ireative Proceduren in Purebasic bzw. in meinem Fall?

@All
Danke für eure (wie immer) extrem schnelle Hilfe.

Re: Procedure in Procedure Extrem häufig aufrufen

Verfasst: 12.04.2011 18:56
von STARGÅTE
Wenn ich deine Prozedur richtig deute, Willst du ein "zufällig" abgerundeten Berg schaffen...

Das kannst du auch mit einem einfachen Gausfilter erreichen.
Dort werden halt einfachgesagt: Die Höhen verschiedener Positionen vermischt ...

Vom Prinzip: Karte durchlaufen und die Höhe von einem Punkt aus einer Misschung all seiner Umgebungspunkte erstellen.

EDIT: Muss leider weg, sonst würde ich dir noch schnell n Beispiel schreiben ...

Re: Procedure in Procedure Extrem häufig aufrufen

Verfasst: 14.04.2011 18:05
von FosJonas
Nur keine hektik Stargate, habe ja jetzt auch lange gebraucht um zu Antworten.

Der Gausfilter würde zwar auch gehen, allerdings habe ich da das Problem das man den Punkt an die Umgebung anpasst und nicht die Umgebung an den Punkt. Da ich das ganze nicht nur zum Map erstellen nutze sollte sich aber die Umgebung an den Punkt anpassen.

Nach langem Tüfteln habe ichs nun so gemacht:

Code: Alles auswählen

#MapX = 32 : #MapZ = 32
Global Dim Map_Height.b(#MapX,#MapZ)
Global Dim ArroundList.i(#MapX*#MapZ*4,2)

Procedure AddArroundMapItem(X.i,Z.i,Height.i)
  
  If Map_Height(X,Z) = 0
    ArroundList(ArroundListCount , 0) = X
    ArroundList(ArroundListCount , 1) = Z
    ArroundList(ArroundListCount , 2) = Height
    ArroundListCount + 1
  EndIf
  
EndProcedure

Procedure CreateMap(Height.b)
  Protected P.i,X.i,Z.i,Y.i
  
  AddArroundMapItem(0,0,Height)
  
  While ArroundList(P,2) <> 0
    
    RandomSeed(ElapsedMilliseconds()+P)
    ArroundList(P,2) + Random(10) - 5
    
    If ArroundList(P,2) = 0
      ArroundList(P,2) = 1
    EndIf
    
    X = ArroundList(P,0)
    Z = ArroundList(P,1)
    Y = ArroundList(P,2)
    
    AddArroundMapItem(X-1,Z,Y)
    AddArroundMapItem(X+1,Z,Y)
    AddArroundMapItem(X,Z+1,Y)
    AddArroundMapItem(X,Z-1,Y)
    
    P + 1
  Wend
  
EndProcedure

CreateMap(128)
Funktioniert blöderweise nicht, gibt nen "Array index out of bounds" beim AddArroundMapItem. Nur selbst nach Stundenlangem Prüfen des Codes kapier ich einfach nicht warum. Die Schleife läuft im Prinzip unendlich Lang weiter, obwohl sie doch eigentlich stoppen sollte sobald die Karte gefüllt ist?

Weis jemand da Rat? Wäre sehr dankbar.

Re: Procedure in Procedure Extrem häufig aufrufen

Verfasst: 14.04.2011 18:21
von STARGÅTE
Naja du fragst ja nirgend ab, ob nicht die Grenzen des Arrays verlassen werden, sonden immer nur, was für ein Wert im Array-Feld steht.

Das heißt vor so etwas:

Code: Alles auswählen

AddArroundMapItem(X-1,Z,Y)
immer erst prüfen ob X > 0 ist, bzw. bei

Code: Alles auswählen

AddArroundMapItem(X+1,Z,Y)
immer erst prüfen ob X < ArraySize(...) bzw. < #MapX ist.

Code: Alles auswählen

    If X > 0     : AddArroundMapItem(X-1,Z,Y) : EndIf
    If X < #MapX : AddArroundMapItem(X+1,Z,Y) : EndIf
    If Z > 0     : AddArroundMapItem(X,Z-1,Y) : EndIf
    If Z < #MapZ : AddArroundMapItem(X,Z+1,Y) : EndIf

Re: Procedure in Procedure Extrem häufig aufrufen

Verfasst: 16.04.2011 11:34
von FosJonas
So, habe es nun endlich hinbekommen danke für eure Hilfe sonst hätte ich es wahrscheinlich nie geschafft.
Das Ergebniss sieht zwar dürftig aus aber der Sinn der Procedure ist erfüllt.

Code: Alles auswählen

#MapX = 32 : #MapZ = 32
Global Dim Map_Height.i(#MapX,#MapZ)
Global Dim ArroundList.i(#MapX*#MapZ*4,2)
Global ArroundListCount

Procedure AddArroundMapItem(X.i,Z.i,Height.i)
  
  If Map_Height(X,Z) = 0
    
    ArroundList(ArroundListCount , 0) = X
    ArroundList(ArroundListCount , 1) = Z
    ArroundList(ArroundListCount , 2) = Height
    ArroundListCount + 1
  EndIf
  
EndProcedure

Procedure CreateMap(Height.b)
  Protected P.i,X.i,Z.i,Y.i
  AddArroundMapItem(0,0,Height)
  
  While ArroundList(P,2) <> 0
    If Map_Height(ArroundList(P,0),ArroundList(P,1)) = 0
      
    RandomSeed(ElapsedMilliseconds()+P)
    ArroundList(P,2) + Random(10) - 5
    
    If ArroundList(P,2) = 0
      ArroundList(P,2) = 1
    EndIf
    
    X = ArroundList(P,0)
    Z = ArroundList(P,1)
    Y = ArroundList(P,2)        
    
    Map_Height(X,Z) = Y
    
    If X > 0     : AddArroundMapItem(X-1,Z,Y) : EndIf
    If X < #MapX : AddArroundMapItem(X+1,Z,Y) : EndIf
    If Z > 0     : AddArroundMapItem(X,Z-1,Y) : EndIf
    If Z < #MapZ : AddArroundMapItem(X,Z+1,Y) : EndIf
    
    EndIf
    P + 1
  Wend
  
EndProcedure

CreateMap(64)
Geändert wurde jetzt die von Stargate erwähnten Prüfungen von X und Z und die Prüfung der Map_Height am Anfang der While Schleife.

Nochmals vielen dank an alle die mir geholfen haben.