Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Zufalls Labyrinth

 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 18.03.2013, 23:03    Titel: Zufalls Labyrinth Antworten mit Zitat

Hi zusammen,

ich versuche mich gerade mit der Generierung eines Zufalls-Labyrinth, leider hab ich da wohl noch ein paar kleinere Probleme...
Um zu prüfen ob alle Wege erreichbar sind hab ich eine fillPath Funktion zum testen wo mir dann aufgefallen ist das bei mir oft ganze Bereiche verschlossen sind (was nicht so schlimm wäre), leider erreicht man dann leider auf keinem Weg vom Start aus das Ziel was am ende wohl fatal wäre...

Hier mal zwei Beispiele: (grün ist start, rot ist ziel, weiss ist wand, grau ist weg bzw hellblau weg vom fillpath)




Am besten wäre es wenn das Labyrinth immer so generiert wird wie dieses zum Beispiel:


Seht ihr irgendwo einen Weg das zu erreichen?
Hier mal mein Beispielcode:
Code:

Randomize Timer

type Vector2
    X as Integer
    Y as Integer
end type

    Function getRandom(Byval min as Integer, Byval max as Integer, Byval granularity as Integer = 1) as Integer
        Dim emergencyexit as Integer
        Dim rndnum as Integer
       
        do
            rndnum = int(rnd*(max-(min-1)))
            If  (rndnum mod granularity) = 0 Then return rndnum
            emergencyexit += 1
        loop while emergencyexit < 99
       
        return 0
    End Function
   
       
    Function genMaze(Byval sizeW as Integer, Byval sizeH as Integer, Byval start as Vector2, Byval goal as Vector2) as byte ptr
        Dim MazeP as byte ptr = NEW byte[sizeW*sizeH]
       
        Dim minLength   as Integer = 1
        Dim maxLength   as Integer
        Dim granularity as Integer
        Dim destination as Integer
        Dim as Integer X,Y,L,dX,dY
       
        MazeP[start.X + (start.Y * sizeW)] = &h02 'start
        MazeP[goal.X  + (goal.Y  * sizeW)] = &h03 'goal
       
        For G as Integer = 4 to 1 step -1
            granularity = 2 ^ G
           
            For W as Integer = 0 to (sizeW*sizeH)
               
                X = getRandom(0,sizeW-1,granularity)
                Y = getRandom(0,sizeH-1,granularity)
                destination = getRandom(0,3)
           
                Select Case destination
                    Case 0 'Left
                        maxLength = sizeW/2
                        L = getRandom(minLength,maxLength)
                        dX = -1 : dY =  0
                    Case 1 'Right
                        maxLength = sizeW/2
                        L = getRandom(minLength,maxLength)
                        dX =  1 : dY =  0
                    Case 2 'Up
                        maxLength = sizeH/2
                        L = getRandom(minLength,maxLength)
                        dX =  0 : dY = -1
                    Case 3 'Down
                        maxLength = sizeH/2
                        L = getRandom(minLength,maxLength)
                        dX =  0 : dY =  1
                End Select
                   
                For ll as Integer = 1 to L
                    If (MazeP[X+(Y*sizeW)]) Then Exit For
                       
                    MazeP[X+(Y*sizeW)] = 1
                    X += dX : Y += dY
                       
                    If (X < 0) OR (X >= sizeW) OR (Y < 0) OR (Y >= sizeH) Then Exit For
                Next ll
       
            Next W
        Next G
       
        return MazeP
    End Function
   



Sub fillPath(byref Maze as byte ptr, byval sizeW as Integer, byval sizeH as Integer, byval posX as Integer, byval posY as Integer, byval init as Integer = 0)
    static fin as Integer
    Dim mappos as Integer
    mappos = posX+(posY*sizeW)
   
    If init then fin = 0
    If Maze[mappos]=&h00 Then Maze[mappos]=&h20' :?posX,posY
    If Maze[mappos]=&h03 Then fin=1
       
    If fin Then Exit Sub
   
    If (posX > 0) and Maze[mappos-1]=&h00 Then fillPath(Maze,sizeW,sizeH,posX-1,posY)
    If (posY > 0) and Maze[mappos-sizeW]=&h00 Then fillPath(Maze,sizeW,sizeH,posX,posY-1)
    If (posX < (sizeW-1)) and Maze[mappos+1]=&h00 Then fillPath(Maze,sizeW,sizeH,posX+1,posY)
    If (posY < (sizeH-1)) and Maze[mappos+sizeW]=&h00 Then fillPath(Maze,sizeW,sizeH,posX,posY+1)
   
End Sub


screenres 800,600,32

Dim myMaze as byte ptr
Dim as Integer C, F
Dim as Vector2 S, G

do
    S = type(rnd*80,rnd*60)
    G = type(rnd*80,rnd*60)
    myMaze = genMaze(80,60,S,G)
   
    fillPath(myMaze,80,60,S.X,S.Y,1)
   
    for y as integer=0 to 59
        for x as integer=0 to 79
            F = myMaze[x+(y*80)]
            Select Case F
                Case &h00 'Floor
                    C = &h222222
                Case &h01 'Wall
                    C = &hFFFFFF
                Case &h02 'Start
                    C = &h00FF00
                Case &h03 'Goal
                    C = &hFF0000
                Case &h20 'test path
                    C = &h3333FF
                Case Else ' error?
                    C = &hFF8800
            End Select
       
            Line(x*10,y*10)-(9+(x*10),9+(y*10)),C,bf
        next x
    next y

    sleep

    Delete[] myMaze
Loop until multikey(&h01)

_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4597
Wohnort: ~/

BeitragVerfasst am: 19.03.2013, 00:07    Titel: Antworten mit Zitat

Ich habe mal wegen eines Wegsuch-Algorithmus ein Labyrinth erstellt, da habe ich ganz einfach anschließend einen zufälligen Weg hindurch freigeräumt grinsen so war zumindest sichergestellt, dass es mindestens einen möglichen Weg gibt.
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 19.03.2013, 02:46    Titel: Antworten mit Zitat

Wäre vielleicht eine Alternative Wert grinsen

hab noch eine Weile an meinem Code gebastelt und lasse mir das Labyrinth neu generieren falls das Ziel vom Start aus nicht erreichbar ist...

Muss mir jetzt nur noch etwas Überlegen für einen Fall wie zB hier wo der Start einfach zu nah am Ziel ist...




und es fehlt mir vielleicht noch ein schönes A* Pathfinding Beispiel

Code:
Randomize Timer

#Define MazeFloor   &h00
#Define MazeWall    &h01
#Define MazeStart   &h02
#Define MazeGoal    &h03
#Define MazePath    &h20

Function getRandom(Byval min as Integer, Byval max as Integer, Byval granularity as Integer = 1) as Integer
    'Dim emergencyexit as Integer
    Dim rndnum as Integer
       
    'do
        rndnum = int(rnd*(max-(min-1)))
        'If  (rndnum mod granularity) = 0 Then return rndnum
        'emergencyexit += 1
    'loop while emergencyexit < 99
       
    return rndnum'min
End Function

Type Vector2
    X as Integer
    Y as Integer
End Type


Type tMaze
    'Private:
    MazeP as byte ptr
    MazeW as Integer  'Width
    MazeH as Integer  'Height
    MazeC as Integer  'control flag
    MazeS as Vector2  'Start position
    MazeG as Vector2  'goal/exit
   
   
    Declare Sub fillwithWalls(byval minLength as Integer, byval maxLength as Integer, byval granularity as Integer, byval numWalls as Integer)
   
    'Public:
   
   
    Declare Sub genMaze(byval size as Vector2, byval start as Vector2, byval goal as Vector2)
    Declare Sub genMaze(byval sizeW as Integer, byval sizeH as Integer)
    Declare Sub delMaze()
   
    Declare Sub fillPath(byval position as Vector2)
    Declare Sub drawMaze()
End Type

Sub tMaze.fillPath(byval position as Vector2)
    If MazeC Then Exit Sub
   
    Dim mappos  as Integer
    Dim maptype as Integer
    Dim FP      as Integer
    mappos = position.X+(position.Y*MazeW)
   
    If MazeP[mappos]=MazeFloor Then MazeP[mappos]=&h20
       
    If (position.X > 0) Then
        maptype = MazeP[mappos-1]
        If maptype = MazeFloor Then FP = FP OR &b0001
        If maptype = MazeGoal  Then MazeC = 1
    End If
   
    If (position.Y > 0) Then
        maptype = MazeP[mappos-MazeW]
        If maptype = MazeFloor Then FP = FP OR &b0010
        If maptype = MazeGoal  Then MazeC = 1
    End If

    If (position.X < (MazeW-1)) Then
        maptype = MazeP[mappos+1]
        If maptype = MazeFloor Then FP = FP OR &b0100
        If maptype = MazeGoal  Then MazeC = 1
    End If

    If (position.Y < (MazeH-1)) Then
        maptype = MazeP[mappos+MazeW]
        If maptype = MazeFloor Then FP = FP OR &b1000
        If maptype = MazeGoal  Then MazeC = 1
    End If
   
    If (FP and &b0001) Then fillPath(type(position.X-1,position.Y))
    If (FP and &b0010) Then fillPath(type(position.X,position.Y-1))
    If (FP and &b0100) Then fillPath(type(position.X+1,position.Y))
    If (FP and &b1000) Then fillPath(type(position.X,position.Y+1))
   
End Sub

Sub tMaze.drawMaze()
    Dim C as UInteger
    Dim F as byte
   
    screenlock
    for y as integer=0 to MazeH-1
        for x as integer=0 to MazeW-1
            F = MazeP[x+(y*MazeW)]
            Select Case F
                Case &h00 'Floor
                    C = &h222222
                Case &h01 'Wall
                    C = &hFFFFFF
                Case &h02 'Start
                    C = &h00FF00
                Case &h03 'Goal
                    C = &hFF0000
                Case &h20 'test path
                    C = &h3333FF
                Case Else ' error?
                    C = &hFF8800
            End Select
       
            Line(x*10,y*10)-(9+(x*10),9+(y*10)),C,bf
        next x
    next y   
    screenunlock
End Sub

Sub tMaze.fillwithWalls(byval minLength as Integer, byval maxLength as Integer, byval granularity as Integer, byval numWalls as Integer)
    Dim mappos as Integer
    Dim rndpos as Vector2
    Dim rnddir as Integer
    Dim rndlen as Integer
    Dim as Integer dX, dY
   
    For NW as Integer = 1 to numWalls
        rndpos.X = granularity * getRandom(0,(MazeW-1)/granularity)
        rndpos.Y = granularity * getRandom(0,(MazeH-1)/granularity)
        rnddir   = getRandom(0,3)
        rndlen   = granularity * getRandom(minLength,maxLength) + 1
       
        Select Case rnddir
            Case 0 'North/Up
                dX =  0 : dY = -1
            Case 1 'East/Right
                dX =  1 : dY =  0
            Case 2 'South/Down   
                dX =  0 : dY =  1
            Case 3 'West/Left
                dX = -1 : dY =  0
        End Select
       
        For L as Integer = 0 to rndLen
           
            mappos = rndpos.X + (rndpos.Y * MazeW)
           
            If MazeP[mappos] Then Exit For
           
            MazeP[mappos] = MazeWall
           
            rndpos.X += dX : rndpos.Y += dY
           
            If (rndpos.X < 0) OR (rndpos.Y < 0) OR (rndpos.X >= MazeW) OR (rndpos.Y >= MazeH) Then Exit For
           
        Next L
       
    Next NW
End Sub


Sub tMaze.genMaze(byval sizeW as Integer, byval sizeH as Integer)
    Dim rndStart as Vector2 = type(rnd*sizeW,rnd*sizeH)
    Dim rndGoal  as Vector2 = type(rnd*sizeW,rnd*sizeH)
    genMaze(type<Vector2>(sizeW,sizeH),rndStart,rndGoal)
End Sub

Sub tMaze.genMaze(byval size as Vector2, byval start as Vector2, byval goal as Vector2)
    Dim mappos as Integer
   
    MazeW = 0
    MazeH = 0
    MazeS = type(0,0)
    MazeG = type(0,0)
    MazeC = 0
   
    Do
        If MazeP Then delMaze()
   
        MazeW = size.X : MazeH = size.Y
   
        MazeP = NEW byte[MazeW * MazeH]
   
        mappos = start.X + (start.Y * MazeW)
   
        If (mappos >= 0) and (mappos < (MazeW * MazeH)) Then
            MazeP[mappos] = MazeStart
            MazeS = start
        Else
            MazeP[0] = MazeStart
            MazeS = type(0,0)
        End If
   
        mappos = goal.X + (goal.Y * MazeW)

        If (mappos >= 0) and (mappos < (MazeW * MazeH)) and ((goal.X<>start.X) OR (goal.Y<>start.Y)) Then
            MazeP[mappos] = MazeGoal
            MazeG = goal
        Else
            MazeP[(MazeW*MazeH)-1] = MazeGoal
            MazeG = type(MazeW-1,MazeH-1)
        End If
   
        fillwithWalls( 4, 6, 16, 100)
        fillwithWalls( 2, 6,  8, 200)
        fillwithWalls( 2, 4,  4, 300)
        fillwithWalls( 1, 4,  2, MazeW*MazeH)
   
        fillPath(MazeS)
        If MazeC Then Exit Do
    Loop
End Sub

Sub tMaze.delMaze()
    If MazeP Then Delete[] MazeP
    MazeW = 0
    MazeH = 0
    MazeS = type(0,0)
    MazeG = type(0,0)
    MazeC = 0
End Sub



screenres 800,600,32

Dim myMaze as tMaze
Do   
    myMaze.genMaze(80,60)
    myMaze.drawMaze()

    sleep
    myMaze.delMaze()
Loop until multikey(&h01)

_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 19.03.2013, 02:55    Titel: Antworten mit Zitat

Vorschlag. Wie wäre es denn, wenn du einen Path zufällig generieren lässt, und um diesen herum "bullshit" setzen lässt.

damit hast du immer einen funktionierenden Path, um den du herum alles mögliche bastelst, das irreführend oder sogar erfolgversprechend werden könnte, anstat per zufall etwas zu generieren.

was meinst du mit "und es fehlt mir vielleicht noch ein schönes A* Pathfinding Beispiel" ?

PS: Code-Collaps wäre wirklich langsam sinvoll. Diese Giga-Postings nehmen immer mehr zu.


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 19.03.2013, 03:05    Titel: Antworten mit Zitat

Mir kam die Idee ein kleines Dungeon/Labyrinth zu erstellen, wollte aber keine 'Level' machen und dachte mir ich bediene mich eines Maze-Algorythmus . Fand anfänglich aber nur auf 'Zellen' aufgebaute:

Hab den Code hier dann mithilfe dieser PDF erstellt die ich gefunden habe:
https://www2.cs.fau.de/EN/teaching/WS2005/GameAlgHS/download/Rathmann-Prozedurale_Labyrinth-Generierung.pdf

Schien mir am geeignetsten, die Idee zufällig einen Path zu erstellen und drumherum zu 'Bauen' wäre ebenfalls einen Versuch Wert, scheint mir aber mindestens genauso 'komplex' zu werden...

btw: hab selbst gar nicht gemerkt das der Code schon wieder so lang geworden ist...

Zitat:
was meinst du mit "und es fehlt mir vielleicht noch ein schönes A* Pathfinding Beispiel" ?


http://de.wikipedia.org/wiki/A*-Algorithmus
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 19.03.2013, 03:10    Titel: Antworten mit Zitat

in der wiki gibts doch n beispiel ... is zwar nicht fb, aber der source sollte sehr leicht in fb zu integrieren sein.


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 19.03.2013, 15:06    Titel: Antworten mit Zitat

Hab versucht ein klein wenig zu optimieren, sollte eigentlich optimal funktionierten (tut es bei kleinen Labyrinthen auch) aber versuche ich ein größeres wie im Beispielcode (400,300) zu erzeugen stürzt das Programm entweder ab oder bleibt hängen...
Hab bereits mit -exx compiliert (ohne meldung) sowie den stack erhöht bzw alle möglichen stack/speicher funktionen ausgeklammert...
Auch den mit NEW reservierten Speicherbereich testweise mit allocate erzeugt (bzw callocate)...

ich finde die Ursache einfach nicht...

http://www.freebasic-portal.de/porticula/mymaze3-1603.html

mit dem Kopf durch die Mauer wollen

im selben Atemzug wie ich den Post geschrieben habe war mir was eingefallen...

Dummerweise hab ich die map-position mit ushort's verrechnet, die positionen aber weit über die 65k grenze hinaus gingen... hab sie zu uintegern geändert und nun funktioniert es ohne weitere probleme...

sorry Kopf schütteln
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 19.03.2013, 15:11    Titel: Antworten mit Zitat

Dies sollte dir helfen: http://ops.ath.cx/code?id=278

PS: Thread-3 kannst du ignorieren. Das is n anderer BUG von FB/C und hat mir dir nix zutun.


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 19.03.2013, 16:15    Titel: Antworten mit Zitat

hmm... wenn ich nun nicht vorher herausgefunden hätte woran es lag, würde ich aus der Info auch nur 'speicherverletzungen' erkennen...

das optimieren aber hat sich aber ein wenig gelohnt, nun wird jedes mal ein sehr schönes Maze generiert (nach 10min auf den Screen gucken noch kein Maze mit Einschlüssen entdeckt...)

http://www.freebasic-portal.de/porticula/perfect-maze-1604.html

Edit: nu hab ich doch EIN MAL ein Einschluss gesehen (sind also doch Möglich aber sehr selten happy)



Ob man das später ohne Hilfe lösen kann ? happy
_________________


Zuletzt bearbeitet von Eternal_pain am 19.03.2013, 16:51, insgesamt einmal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 19.03.2013, 16:22    Titel: Antworten mit Zitat

jo. das is richtig .. is ne speicherverletzung. In dem Log findest du allerdigns sogar die Orte, wo diese speicherfehler auftreten. test7.bas: zeile 138 z.B. ... anhand der info kannst doch schon deutlich zielgerichteter nach dem fehler suchen.

hinzu kommt, das dieses log dir auch sagt, was für eine art von speicherverletzung es ist.
Invalid write of size 1 ... ingültiger schreibvesuch von 1 byte länge
Address 0x459e598 is not stack'd, malloc'd or (recently) free'd ... das ganze an adresse xyz, welche nicht auf dem stack liegt, niemals allociert und oder früher wieder freigegeben wurde.

sprich, du hast versuch auf speicherbereiche zuzugreifen, wie du nie besessen hast.

Wäre also mal sinvoll, die adressen zu prüfen, welche du nutzt. Das zeug zwischen [ und ].

Einige Fehler können unter umständen nichtmal dramatisch auftreten. sondern erst in komischen fällen, was dann dazu führt, das du dich tot suchst Zunge rausstrecken


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
dreael
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 2507
Wohnort: Hofen SH (Schweiz)

BeitragVerfasst am: 19.03.2013, 22:55    Titel: Antworten mit Zitat

Früheres QB-Projekt von mir:

http://www.dreael.ch/Deutsch/Download/Labyrinth.html

=> Damals hatte ich mich auch einmal mit passenden Algorithmen auseinandergesetzt bzw. dort selber etwas entwickelt. => Du kannst dort sogar mit einer Parameterzahl die Generierung beeinflussen.
_________________
Teste die PC-Sicherheit mit www.sec-check.net
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 20.03.2013, 18:32    Titel: Antworten mit Zitat

Anfangs hatte ich auch versucht ein wenig mehr Flexibilität einzubauen wenn es darum ging wie viel und wie lange Wände generiert werden sollen...
Bin aber immer weiter davon ab, und generiere nach 'Regeln' wie in dem oben verlinkten PDF beschrieben und erhalte inzwischen eigentlich recht tolle Labyrinthe... Einschlüsse sind selten und meistens recht klein (je größer das zu generierende Labyrinth um so höher die Möglichkeit und Größe der Einschlüsse)
Mir jedenfalls gefällt es jetzt schon ganz gut

Habe allerdings noch ein kleines Problem (hauptsächlich bei großen Labyrinthe)

Und zwar stößt meine rekursive fill-Routine (zum prüfen) bzw. der Stack irgendwann an seine Grenzen...

Hier mal ein Beispiel (Versuch) als Farbfüller, der schon sehr früh aufgibt:
Code:

Const scrWidth  as Integer = 800
Const scrHeight as Integer = 600

Namespace scrfill
    Dim pColor as Uinteger
    Dim fColor as UInteger
   
    Declare Sub fill(byval posX as Integer, byval posY as Integer, byval col as Uinteger)
    Declare Sub nfill(byval posX as Integer, byval posY as Integer)
   
    Sub fill(byval posX as Integer, byval posY as Integer, byval col as Uinteger)
        pColor = point(posX,posY)
        fColor = col
       
        nfill(posX, posY)
    End Sub
   
    Sub nfill(byval posX as Integer, byval posY as Integer)
        static nstack as uinteger
        nstack += 1
       
        open cons for output as #99 : print #99,nstack:close #99
       
        if point(posX,posY) = pColor Then pset(posX,posY),fColor
       
        If (posX > 0            ) andalso point(posX-1,posY  )=pColor Then nfill(posX-1,posY  )
        If (posY > 0            ) andalso point(posX  ,posY-1)=pColor Then nfill(posX  ,posY-1)
        If (posX < (scrWidth-1 )) andalso point(posX+1,posY  )=pColor Then nfill(posX+1,posY  )
        If (posY < (scrHeight-1)) andalso point(posX  ,posY+1)=pColor Then nFill(posX  ,posY+1)
       
        nstack -= 1
    End Sub

End Namespace


screenres scrWidth,scrHeight,32

line(1,1)-(scrWidth-2,scrHeight-2),&hFFFFFFFF

scrfill.fill(100,100,&hFF0000)

sleep

   


Irgendeine Idee das ganze wenigstens halb oder ganz interativ zu gestalten?
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4597
Wohnort: ~/

BeitragVerfasst am: 20.03.2013, 20:07    Titel: Antworten mit Zitat

evtl. eine Richtung (z. B. nach rechts) iterativ machen statt rekursiv. Und sonst gibt es natürlich auch immer noch eine BASIC-eigene Füllroutine PAINT.

edit: Es sollte auch gehen, dass du waagrecht generell iterativ vorgehst und nur bei auf/ab die Rekursion brauchst.
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
dreael
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 2507
Wohnort: Hofen SH (Schweiz)

BeitragVerfasst am: 20.03.2013, 20:53    Titel: Antworten mit Zitat

Zu meiner seinerzeitigen Variante: Iterativer Algorithmus mit einer List, die zu Beginn 1 Position enthält, ausserdem Streichtabelle in der Grösse vom Labyrinth.

While (Liste noch nicht leer)

Algorithmus pro Iterationsschritt: Zufälliger Eintrag in Liste suchen, ebenso zufällige Richtung, die aber noch gemäss Streichtabelle noch nicht entdeckt ist. => Zu diesem Feld hin Durchgang "graben", Zielfeld streichen und auf die Liste nehmen.

Falls fürs ausgewählte Feld keine unentdeckten Nachbarfelder (Streichtabelle) mehr gibt, dann gewähltes Feld aus Liste entfernen.

Wend

=> Ergibt dann einen Lybrinth-Entstehungsprozess, der mit dem Wachstum eines Wurzelballen einer Pflanze vergleichbar ist: Jedes Ende kann wachsen, solange es noch freie Erde hat. Am Schluss wird für die Positionierung des Ein- und Ausgangs der längste Weg gesucht.
_________________
Teste die PC-Sicherheit mit www.sec-check.net
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 20.03.2013, 21:18    Titel: Antworten mit Zitat

Bezüglich PathFind hab ich mal was gebastelt: http://www.freebasic-portal.de/porticula/getpath-bas-1605.html


MfG + HF
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 21.03.2013, 21:47    Titel: Antworten mit Zitat

Gestern Abend hatte ich noch ein paar Versuche angestellt um mich vor einer LinkedList zu drücken (weil ich damit immer so meine Probleme habe) hat zwar funktioniert war aber furchtbar langsam (mehrere Minuten)

Hab mich dann nun doch noch dazu durchgerungen eine LinkedList zu basteln, damit geht es jetzt angemessener Geschwindigkeit schon ganz gut (getestet mit einem 1920,1080 Labyrinth (mehr kann ich auf meinem Schirm nicht anzeigen happy))

Auch wenn es funktioniert, bin ich mir meiner LinkedList nicht zu hundert prozent sicher (trau mir da nicht ganz happy)
speziell die DelEntry und DestroyList
Wenn da einer 'nen kurzen Blick drauf werfen mag?!
Code:

Type tListNode
    NextEntry  as tListNode ptr
    PrevEntry  as tListNode ptr
   
    EntryValue as Integer
End Type

Type tList
    Declare Sub AddEntry(byval Value as Integer)
    Declare Sub DelEntry(byref ListNode as tListNode ptr)
    Declare Sub DestroyList()
   
    FirstEntry as tListNode ptr
    LastEntry  as tListNode ptr
End Type


Sub tList.AddEntry(byval Value as Integer)
    Dim NewEntry as tListNode ptr = NEW tListNode
   
    NewEntry -> EntryValue = Value
   
    If (LastEntry = 0) Then
        FirstEntry = NewEntry
        LastEntry  = NewEntry
        Exit Sub
    End If
   
    If LastEntry Then
        NewEntry -> PrevEntry = LastEntry
        LastEntry -> NextEntry = NewEntry
        LastEntry = NewEntry
    End If
End Sub

Sub tList.DestroyList()
    Dim ThisNode as tListNode ptr
    Dim TempNode as tListNode ptr
    ThisNode = LastEntry
   
    Do
        If ThisNode Then
            TempNode = ThisNode -> PrevEntry
            DelEntry(ThisNode)
            ThisNode = TempNode
        End If
    Loop while ThisNode
End Sub

Sub tList.DelEntry(byref ListNode as tListNode ptr)
    If ListNode -> NextEntry Then ListNode -> NextEntry -> PrevEntry = ListNode -> PrevEntry
    If ListNode -> PrevEntry Then ListNode -> PrevEntry -> NextEntry = ListNode -> NextEntry
   
    If FirstEntry = ListNode Then FirstEntry = FirstEntry -> NextEntry
    If LastEntry  = ListNode Then LastEntry  = LastEntry -> PrevEntry
   
    Delete ListNode
End Sub


Den ganzen Mazecode gibts dann hier (zum testen...)
http://www.freebasic-portal.de/porticula/mymaze4-1607.html

@ThePuppetMaster
auf dein PathFind-Code werd ich mich direkt mal draufstürzen zwinkern
Danke für die Mühe...
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 21.03.2013, 23:37    Titel: Antworten mit Zitat

reiner info-code:


einfach last als temp ptr nutzen. da die liste eh schlussendlich leer is (0) ists egal welche var man nimmt.
Code:

Sub list_destroy(byref first, byref last)
do until first = 0
    last = first->next
    deallocate(first)
    first = last
loop
end sub


1. schaun, ob nach dem item noch eines kommt. wenn ja, dan dieses darüber informieren, das sein vorheriger jetzt der vorherige vom item is
2. selbes mit dem vorherigem vom item
3. schaun, ob das item eventuell das erste is, wenn ja, dann bei first das nächste vom item setzen
4. selbes mit dem letztem
5. item löschen
6. fertig
7. freuen Zunge rausstrecken
Code:

sub list_del(byval item, byref first byref last)
if item->next <> 0 then item->next->prev = item->prev
if item->prev <> 0 then item->prev->next = item->next
if first = item then first = item->next
if last = item then last = item->prev
deallocate(item)
end sub


so kannst du eigentlich jede double-linked list leeren und items daraus löschen.


MfG
TPM


EDIT: bei deinem clear gibts n prob. du schreibst
Code:

'...
Loop while ThisNode

das is GANZ GANZ schlecht.
wenn die liste leer is, dann durchläuft deine do-loop min. 1x die schleife.

besser ist
Code:

do while ThisNode
'...

hier wird bei 0 schon die schleife übersprungen und nicht erst min. 1x durchlaufen.
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 22.03.2013, 15:47    Titel: Antworten mit Zitat

ThePuppetMaster hat Folgendes geschrieben:

EDIT: bei deinem clear gibts n prob. du schreibst
Code:

'...
Loop while ThisNode

das is GANZ GANZ schlecht.
wenn die liste leer is, dann durchläuft deine do-loop min. 1x die schleife.

besser ist
Code:

do while ThisNode
'...

hier wird bei 0 schon die schleife übersprungen und nicht erst min. 1x durchlaufen.

Das war jetzt kein wirkliches Problem, aber sieht letztenendes besser aus:
Code:

Sub tList.DestroyList()
    while FirstEntry
        LastEntry = FirstEntry -> NextEntry
        Delete FirstEntry
        FirstEntry = LastEntry
    wend
End Sub

Schwerwiegend allerdings war, bei meinem delEntry die übergabe per byref, das führte zu schweren Fehlern...

sollte aber nun wirklich funktionieren...

Hab mir inzwischen mal deine Pathfind-Routine angesehen... hab sie zwar nicht ganz überblicken können. Habe meine aber (bis jetzt) glaube auf dem selben Prinzip aufgebaut, das überraschend einfach ist lächeln

http://www.freebasic-portal.de/porticula/mymazepregetpath-1608.html
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1837
Wohnort: [JN58JR]

BeitragVerfasst am: 22.03.2013, 16:29    Titel: Antworten mit Zitat

Naja.. prinzipiel ist es ja recht simpel.
Ziel = wertigkeit 0
nachbarpixel vom ziel = 1
nachbar vom nachbarpixel = 2
usw.

im endeffekt machst du nichts anderes als, je weiter du vom ziel weg kommst, desto gröser wird der wert in den pixeln.

vergleichbar mit einem https://lh6.googleusercontent.com/_MRd4TuQSEag/Tdu_5RXJR1I/AAAAAAAAB4w/9LYbqOymJAg/BrushAlpha.png

wobei weis 0 und schwarz N is.

dann kann man von jeder beliebigen position aus die entfernung anhand des wertes auf der position ermitteln, udn durch dem folgen von N nach 0, lässt sich der weg ermitteln.


PS: Clear: joar .. das hätte sich nur dann schiwerig ausgewirkt, wenn du eine leere liste hättest löschen wollen.


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]


Zuletzt bearbeitet von ThePuppetMaster am 23.03.2013, 17:55, insgesamt einmal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 23.03.2013, 10:02    Titel: Antworten mit Zitat

ThePuppetMaster hat Folgendes geschrieben:
PS: Clear: joar .. das hätte sich nur dann schiwerig ausgewirkt, wenn du eine leere liste hättest löschen wollen.

Naja, das Problem hätte ja die If-Abfrage im inneren verhindert
Code:
If ThisNode Then

Trotzdem ist Deine Variante wesentlich Eleganter und kürzer zwinkern

ThePuppetMaster hat Folgendes geschrieben:
Naja.. prinzipiel ist es ja recht simpel.
Ziel = wertigkeit 0
nachbarpixel vom ziel = 1
nachbar vom nachbarpixel = 2
usw.


So in etwa hab ich das Prinzip auch übernommen, nur umgekehrt.. bei mir hat Start den Wert '1' und geht dann weiter bis zum Ziel bzw den Feld das am nächsten am angegebenen Ziel dran ist (Falls Ziel zB. eine Wand ist...)

So ist daraus eine recht überschaubare Funktion geworden...
EDIT: http://www.freebasic-portal.de/porticula/mymaze-pathfind-1611.html

Code:

Function tMaze.getPath(byval fromX as Integer, byval fromY as Integer, byval targetX as Integer, byval targetY as Integer) as Integer ptr
    Dim PathMap    as Integer ptr
    Dim PathList   as Integer ptr
    Dim PathLength as Integer
    Dim frompos    as Integer     = fromX+(fromY*MazeW)
    Dim targetpos  as Integer     = targetX+(targetY*MazeW)
    Dim mappos     as Integer
    Dim nearestpos as Integer
    Dim distance   as Double
    Dim distanceL  as Double      = MazeW*MazeH
   
    Dim as integer tX,tY
   
    Dim fillList as tList
    fillList.AddEntry(frompos)
   
    If (frompos < 0) or (frompos > ((MazeW*MazeH)-1)) Then return 0
   
    PathMap = NEW Integer[MazeW*MazeH]
   
    While fillList.FirstEntry
        mappos = fillList.FirstEntry -> EntryValue
        fillList.DelEntry(fillList.FirstEntry)
       
        PathMap[mappos] += 1 'Set PathCost
       
        tX = mappos mod MazeW
        tY = mappos \ MazeW
       
        distance = Distance2(tX,tY,targetX,targetY)
        If (distance < distanceL) Then
            distanceL  = distance
            nearestpos = mappos
        End If
       
        If (mappos = targetpos) then exit while
       
        If (tX > 0)         andalso ( (MazeP[mappos-1]     < MazeWall) and PathMap[mappos-1]     = 0 ) Then fillList.AddEntry(mappos-1)     : PathMap[mappos-1]     = PathMap[mappos]
        If (tY > 0)         andalso ( (MazeP[mappos-MazeW] < MazeWall) and PathMap[mappos-MazeW] = 0 ) Then fillList.AddEntry(mappos-MazeW) : PathMap[mappos-MazeW] = PathMap[mappos]
        If (tX < (MazeW-1)) andalso ( (MazeP[mappos+1]     < MazeWall) and PathMap[mappos+1]     = 0 ) Then fillList.AddEntry(mappos+1)     : PathMap[mappos+1]     = PathMap[mappos]
        If (tY < (MazeH-1)) andalso ( (MazeP[mappos+MazeW] < MazeWall) and PathMap[mappos+MazeW] = 0 ) Then fillList.AddEntry(mappos+MazeW) : PathMap[mappos+MazeW] = PathMap[mappos]
    Wend
   
    PathLength                    = PathMap[nearestpos]
    PathList                      = New Integer[PathLength+1]
    PathList[0]                   = PathMap[nearestpos]
    PathList[PathMap[nearestpos]] = nearestpos
   
    Do
        mappos               = nearestpos
        PathLength           = PathMap[mappos]
        PathList[PathLength] = mappos
        If (PathLength = 1) Then Exit Do
       
        tX = mappos mod MazeW : tY = mappos \ MazeW
       
        If (tX > 0)         andalso PathMap[mappos-1]     = PathLength-1 Then nearestpos -= 1     : continue do
        If (tY > 0)         andalso PathMap[mappos-MazeW] = PathLength-1 Then nearestpos -= MazeW : continue do
        If (tX < (MazeW-1)) andalso PathMap[mappos+1]     = PathLength-1 Then nearestpos += 1     : continue do
        If (tY < (MazeW-1)) andalso PathMap[mappos+MazeW] = PathLength-1 Then nearestpos += MazeW : continue do
        exit do
    Loop
       
    fillList.DestroyList()
    Delete[] PathMap
   
    return PathList
End Function

_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.

 Impressum :: Datenschutz