Index

Putting It All Together

Now all that is left to do is create the graphics context, create an instance of our maze, then draw the maze in a loop. We will add the ability to create a new maze by pressing the N key. The code looks like this.

SeedRnd(MilliSecs())
Local maze:TMaze = TMaze.Create(10,15)

Graphics 400,600
While Not KeyHit(KEY_ESCAPE) And Not AppTerminate()
	Cls
	maze.Draw(40,40)
	Flip
	If KeyHit(KEY_N) Then maze = TMaze.Create(10,15)
Wend

This will create random mazes with only one path from any cell to another.

The program, in its entirety looks like this.

SuperStrict

Type TCell
	Field paths:Int
	
	Const North:Int = 1
	Const East:Int = 2
	Const South:Int = 4
	Const West:Int = 8
	
	Field _north:TCell, _east:TCell, _south:TCell, _west:TCell
	
	Method Destroy()
		_north = Null
		_east = Null
		_south = Null
		_west = Null
	End Method
	
	Method Link:TCell(Direction:Int)
		paths :| Direction
		Select Direction
			Case North
				_north.paths :| South
				Return _north
			Case South
				_south.paths :| North
				Return _south
			Case East
				_east.paths :| West
				Return _east
			Case West
				_west.paths :| East
				Return _west
		End Select
	End Method
	
	Method getUnvisited:Int[]()
		Local uv:Int[4]
		Local top:Int = 0
		If _north And _north.paths = 0
			uv[top] = North
			top :+ 1
		End If
		If _east And _east.paths = 0
			uv[top] = East
			top :+ 1
		End If
		If _south And _south.paths = 0
			uv[top] = South
			top :+ 1
		End If
		If _west And _west.paths = 0
			uv[top] = West
			top :+ 1
		End If
		
		If top = 0 Then Return Null
		Return uv[..top]
	End Method
	
End Type

Type TMaze
	Field grid:TCell[,]
	Field Width:Int, Height:Int
	
	Function Create:TMaze(Width:Int, Height:Int)
		Local maze:TMaze = New TMaze
		maze.Width = Width
		maze.Height = Height
		
		maze.grid = New TCell[Width,Height]
		
		For Local y:Int = 0 Until Height
			For Local x:Int = 0 Until Width
				maze.grid[x,y] = New TCell
			Next
		Next
		
		For Local y:Int = 0 Until Height
			For Local x:Int = 0 Until Width
				If y > 0 Then maze.grid[x,y]._north = maze.grid[x,y-1]
				If x < Width-1 Then maze.grid[x,y]._east = maze.grid[x+1,y]
				If y < Height-1 Then maze.grid[x,y]._south = maze.grid[x,y+1]
				If x > 0 Then maze.grid[x,y]._west = maze.grid[x-1,y]
			Next
		Next
		
		Local list:TList = CreateList()
		list.AddLast(maze.grid[Rand(0,Width-1),Rand(0,Height-1)])
		
		While Not list.IsEmpty()
			Local cell:TCell = TCell(list.Last()) 'Recursive Backtracking
			'Local cell:TCell = TCell(list.ValueAtIndex(Rand(0,list.Count()-1))) 'Growing Tree
			Local directions:Int[] = cell.getUnvisited()
			If directions = Null
				list.Remove(cell)
			Else
				list.AddLast(cell.Link(directions[Rand(0,directions.length-1)]))
			End If
		Wend
		Return maze
	End Function
	
	Method Draw(w:Int, h:Int)
		For Local y:Int = 0 Until Height
			For Local x:Int = 0 Until Width
				If grid[x,y].paths & TCell.North = 0 Then DrawLine x*w,y*h,x*w+w,y*h
				If grid[x,y].paths & TCell.East = 0 Then DrawLine x*w+w-1,y*h,x*w+w-1,y*h+h
				If grid[x,y].paths & TCell.South = 0 Then DrawLine x*w,y*h+h-1,x*w+w,y*h+h-1
				If grid[x,y].paths & TCell.West = 0 Then DrawLine x*w,y*h,x*w,y*h+h
			Next
		Next
	End Method
			
	Method Delete()
		For Local x:Int = 0 Until Width
			For Local y:Int = 0 Until Height
				grid[x,y].Destroy()
			Next
		Next
	End Method
End Type

SeedRnd(MilliSecs())
Local maze:TMaze = TMaze.Create(10,15)

Graphics 400,600
While Not KeyHit(KEY_ESCAPE) And Not AppTerminate()
	Cls
	maze.Draw(40,40)
	Flip
	If KeyHit(KEY_N) Then maze = TMaze.Create(10,15)
Wend

In the next part, we will be modifying our Cell and Maze classes to rid the dead ands and make the maze more "Pac-Man" like.

Index

Created with Tutorial Markup (c)2018 James Chamblin