I then wanted to build a maze!

I decided to try the "Hunt-and-Kill algorithm" and wrote my own version of it.
Feel free to play around with it or implement some other algorithm and then post the new code here!
Note: If you set drawDelay to 0 it will draw it faster!
EDIT:My improved (faster and more random) algorithm is here: http://www.purebasic.fr/english/viewtop ... 82#p346482
Code: Select all
;Maze example by Joakim L. Christiansen
;Feel free to use and abuse!
;
;Extra credits to:
;http://weblog.jamisbuck.org/2011/2/7/maze-generation-algorithm-recap
EnableExplicit
#main=0
#main_image=0
Global wantedWidth=800, wantedHeight=600
Global blockSize=18
Global mazeWidth = Round(wantedWidth/blockSize,#PB_Round_Up)
Global mazeHeight = Round(wantedHeight/blockSize,#PB_Round_Up)
Global Dim maze(mazeWidth,mazeHeight)
Global image, drawDelay = 10
Procedure.l passageAllowed(fromX,fromY,toX,toY)
Protected i,u,result
If toX>0 And toX<mazeWidth And toY>0 And toY<mazeHeight
result=#True
If maze(toX,toY)=0
result = #False
EndIf
If maze(toX,toY-1)=0 And toY-1<>fromY
result = #False
EndIf
If maze(toX,toY+1)=0 And toY+1<>fromY
result = #False
EndIf
If maze(toX-1,toY)=0 And toX-1<>fromX
result = #False
EndIf
If maze(toX+1,toY)=0 And toX+1<>fromX
result = #False
EndIf
EndIf
ProcedureReturn result
EndProcedure
Procedure.l moveRandomDirection(*x.long,*y.long)
Protected result, NewList possibleDirection()
ClearList(possibleDirection())
If passageAllowed(*x\l,*y\l, *x\l,*y\l-1) ;up
AddElement(possibleDirection()): possibleDirection() = 0
EndIf
If passageAllowed(*x\l,*y\l, *x\l,*y\l+1) ;down
AddElement(possibleDirection()): possibleDirection() = 1
EndIf
If passageAllowed(*x\l,*y\l, *x\l-1,*y\l) ;left
AddElement(possibleDirection()): possibleDirection() = 2
EndIf
If passageAllowed(*x\l,*y\l, *x\l+1,*y\l) ;right
AddElement(possibleDirection()): possibleDirection() = 3
EndIf
If ListSize(possibleDirection()) > 0
SelectElement(possibleDirection(),Random(ListSize(possibleDirection())-1))
Select possibleDirection()
Case 0: *y\l-1
Case 1: *y\l+1
Case 2: *x\l-1
Case 3: *x\l+1
EndSelect
maze(*x\l,*y\l) = 0
result = #True
Else
result = #False
EndIf
ProcedureReturn result
EndProcedure
Procedure drawPassage(x,y)
Protected round1,round2,round3,round4
If maze(x,y-1)=1
If maze(x+1,y)=1 ;top right
round1=#True
EndIf
If maze(x-1,y)=1 ;top left
round2=#True
EndIf
EndIf
If maze(x,y+1)=1
If maze(x+1,y)=1 ;bottom right
round3=#True
EndIf
If maze(x-1,y)=1 ;bottom left
round4=#True
EndIf
EndIf
RoundBox(x*blockSize,y*blockSize,blockSize,blockSize,7,7,RGB(180,180,180))
If Not round1
Box(x*blockSize+blockSize/2,y*blockSize,blockSize/2,blockSize/2,RGB(180,180,180))
EndIf
If Not round2
Box(x*blockSize,y*blockSize,blockSize/2,blockSize/2,RGB(180,180,180))
EndIf
If Not round3
Box(x*blockSize+blockSize/2,y*blockSize+blockSize/2,blockSize/2,blockSize/2,RGB(180,180,180))
EndIf
If Not round4
Box(x*blockSize,y*blockSize+blockSize/2,blockSize/2,blockSize/2,RGB(180,180,180))
EndIf
EndProcedure
Procedure drawMaze()
Protected x,y
If StartDrawing(ImageOutput(image))
Box(0,0,mazeWidth*blockSize,mazeHeight*blockSize,#Black)
For y=0 To mazeHeight
For x=0 To mazeWidth
If maze(x,y) = 1
Box(x*blockSize,y*blockSize,blockSize,blockSize,RGB(0,0,0))
Else
drawPassage(x,y)
EndIf
Next
Next
StopDrawing()
SetGadgetState(#main_image,ImageID(image))
EndIf
EndProcedure
Procedure createMaze(d)
Protected x,y, scanY, scanX, mazeComplete
For x=0 To mazeWidth ;fill with walls
For y=0 To mazeHeight
maze(x,y) = 1
Next
Next
x = Random(mazeWidth-2)+1
y = Random(mazeHeight-2)+1
maze(x,y) = 0 ;place first brick
Repeat
If moveRandomDirection(@x,@y) = #False
;Debug "end reached, finding new position..."
For scanY=2 To mazeHeight-1
For scanX=1 To mazeWidth-1
If maze(scanX,scanY) = 0
If moveRandomDirection(@scanX,@scanY)
;Debug "moved"
x = scanX
y = scanY
Break 2
EndIf
EndIf
Next
If scanY=mazeHeight-1
mazeComplete = #True
EndIf
Next
EndIf
If drawDelay
drawMaze()
Delay(drawDelay)
EndIf
Until mazeComplete
;Debug "Maze building completed!"
drawMaze()
Delay(2000)
CreateThread(@createMaze(),0)
EndProcedure
image = CreateImage(#PB_Any,(mazeWidth+1)*blockSize,(mazeHeight+1)*blockSize,24)
OpenWindow(#main,0,0,(mazeWidth+1)*blockSize,(mazeHeight+1)*blockSize,"JLC's Maze Example v1.2",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
ImageGadget(#main_image,0,0,(mazeWidth+1)*blockSize,(mazeHeight+1)*blockSize,ImageID(image))
CreateThread(@createMaze(),0)
Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow
