RE: To: Evan Marshall (Maze Maker)

new topic     » topic index » view thread      » older message » newer message

> I'm glad you found it interesting.  I was thinking about making a 3D 
> maze and decided a 2D one would be easier to start with.
> I found an algorithm very similar to yours somewhere on the net (I can't 
> 
> remember where :(   ) and decided to go for simplicity(?) over speed for 
> 
> the first draft.  I plan on going back to increase the speed later, as 
> right now I have more time to wait for a program to run than I do to 
> develop it!
> I am also going to make the maze printable and am working on a print 
> preview routine.  (That should take me quite awhile!)
> 
> Don Phillips wrote:

Yes, I found it very interesting.  Its good to try something new every 
once in a while and optimizing this code was alot of fun.  I was able to 
speed it up even further and reduce the code in the main loop quite a 
bit from the one I posted last.  Also I was able to make the status 
indicator consistant in movement.

I think I like this version the best.  Not only is it faster, shorter, 
and easier to understand, I believe it makes better overall (and harder) 
mazes to solve.

-=-=-=-=-=-=-=-=-=-

without warning
include Win32Lib.ew

-- register controls with win32lib
constant
MainWin		= create( Window, "Maze", NULL, 0.1, 0.1, 0.8, 0.8, 
or_all({WS_CLIPCHILDREN,WS_CLIPSIBLINGS}) ),
Canvas		= create( Window, "", MainWin, 0, 0, 1, 1, 
{WS_CHILD,WS_VISIBLE,WS_DLGFRAME,WS_CLIPCHILDREN,WS_CLIPSIBLINGS} ),
MaxXLbl		= createEx( EditText, "", Canvas, 14, 7, 50, 15, 
{WS_CHILD,WS_VISIBLE,WS_DISABLED}, {0} ),
MaxYLbl		= createEx( EditText, "", Canvas, 74, 7, 50, 15, 
{WS_CHILD,WS_VISIBLE,WS_DISABLED}, {0} ),
EditX		= create( EditText, "20", Canvas, 10, 22, 50, 20, ES_NUMBER ),
EditY		= create( EditText, "20", Canvas, 70, 22, 50, 20, ES_NUMBER ),
RunMaze		= create( DefPushButton, "Make Maze", Canvas, 131, 18, 140, 29, 
0 ),
Status		= create( ProgressBar, "", Canvas, 0, 0, 1, 1, 0 )

-- define globals
sequence	NewPos

-- remove a wall in specified direction
procedure RemoveWall( integer Direction )
	if Direction = 1 then
		drawLine( MainWin, (NewPos[1]-1)*10+1, (NewPos[2]-1)*10, 
(NewPos[1]-1)*10+10, (NewPos[2]-1)*10 )
	elsif Direction = 2 then
		drawLine( MainWin, (NewPos[1]-1)*10, (NewPos[2]-1)*10+1, 
(NewPos[1]-1)*10, (NewPos[2]-1)*10+10 )
	elsif Direction = 3 then
		drawLine( MainWin, (NewPos[1]-1)*10+10, (NewPos[2]-1)*10+1, 
(NewPos[1]-1)*10+10, (NewPos[2]-1)*10+10 )
	else
		drawLine( MainWin, (NewPos[1]-1)*10+1, (NewPos[2]-1)*10+10, 
(NewPos[1]-1)*10+10, (NewPos[2]-1)*10+10 )
	end if
end procedure

-- make the maze
procedure makeMaze()
	integer Direction
	integer Index
	integer PosX
	integer PosY
	integer	RoomsX
	integer	RoomsY
	integer	UsedRooms
	sequence Grid
	sequence Mask	
	sequence Move	
	sequence Path
	sequence Size
	sequence Slice

	-- clear screen
	repaintWindow( MainWin )

	-- get size of grid
	Size = value( getText(EditX) )
	RoomsX = Size[ 2 ]
	Size = value( getText(EditY) )
	RoomsY = Size[ 2 ]

	-- enforce maximums
	Size = getClientRect( MainWin )
	if RoomsX > floor((Size[3] - 20) / 10) then
		setText( EditX, sprintf( "%d", {floor((Size[3] - 20) / 10)} ))
		RoomsX = floor((Size[3] - 20) / 10)
	end if
	if RoomsY > floor((Size[4] - 80) / 10) then
		RoomsY = floor((Size[4] - 80) / 10)
		setText( EditY, sprintf( "%d", {floor((Size[4] - 80) / 10)} ))
	end if

	-- set status indicator range to maximum
	UsedRooms = 0
	setScrollRange( Status, 0, RoomsX * RoomsY * 2 )

	-- initialize grid
	Grid = {}
	Grid &= { repeat( 0, RoomsX+2 ) }
	Grid &= repeat( 0 & repeat( 1, RoomsX ) & 0, RoomsY )
	Grid &= { repeat( 0, RoomsX+2 ) }

	-- draw initial grid on screen
	setPenColor( MainWin, Yellow )
	for IterY = 0 to RoomsY do
		drawLine( MainWin, 10, IterY*10+10, RoomsX*10+10, IterY*10+10 )
	end for
	for IterX = 0 to RoomsX do
		drawLine( MainWin, IterX*10+10, 10, IterX*10+10, RoomsY*10+10 )
	end for
	setPenColor( MainWin, Black )

	-- set random initial position
	PosX = rand( RoomsX ) + 1
	PosY = rand( RoomsY ) + 1
	Grid[ PosY ][ PosX ] = 0
	
	NewPos = { PosX, PosY }
	Mask = { 0, 1, 0, 2, 0, 3, 0, 4, 0}
	Move = { {0,-1}, {-1,0}, {1,0}, {0,1} }
	
	Index = 2
	Path = repeat( {}, RoomsX * RoomsY + 1 )
	Path[2] = NewPos
	
	while Index != 1 do
		-- update the indicator and let winlib handle events
		UsedRooms += 1
		setScrollPos( Status, UsedRooms )
		doEvents( 0 )

		-- get movement grid slice
		Slice = {}
		for SliceIter = -1 to 1 do
			Slice &= Grid[ NewPos[2]+SliceIter ][ NewPos[1]-1..NewPos[1]+1 ]
		end for

		-- mask to find valid move positions
		Slice = reverse( sort( (Slice and Mask) * Mask ))

		if not Slice[1] then -- no valid moves, remove from path
			Index -= 1
			NewPos = Path[ Index ]
		else -- move in random direction
			Direction = Slice[ rand(find(0,Slice)-1) ]
			RemoveWall( Direction )
			NewPos += Move[ Direction ]
			Index += 1
			Path[ Index ] = NewPos
			Grid[ NewPos[2] ][ NewPos[1] ] = 0
		end if
	end while

	-- maze done, cut out random top and bottom piece
	PosX = rand( RoomsX ) + 1
	drawLine( MainWin, (PosX-1)*10+1, 10, (PosX-1)*10+10, 10 )
	PosX = rand( RoomsX ) + 1
	drawLine( MainWin, (PosX-1)*10+1, RoomsY*10+10, (PosX-1)*10+10, 
RoomsY*10+10 )

	-- clear status indicator
	setScrollPos( Status, 0 )
end procedure

-- run the maze algorithm
procedure onClick_RunMaze()
	makeMaze()
end procedure
onClick[ RunMaze ] = routine_id( "onClick_RunMaze" )

-- resize controls to parent
procedure onResize_MainWin( integer Style, integer CX, integer CY )
	setRect( Canvas, 0, CY-60, CX, 60, True )
	setRect( Status, 283, 23, CX-300, 18, True )

	setText( MaxXLbl, sprintf( "Max %d", {floor((CX - 20) / 10)} ))
	setText( MaxYLbl, sprintf( "Max %d", {floor((CY - 80) / 10)} ))
end procedure
onResize[ MainWin ] = routine_id( "onResize_MainWin" )

-- initialize
procedure onOpen_MainWin()
	setWindowBackColor( MainWin, Black )
	setWindowBackColor( MaxXLbl, getSysColor(COLOR_BTNFACE) )
	setWindowBackColor( MaxYLbl, getSysColor(COLOR_BTNFACE) )
	setFocus( EditX )
end procedure
onOpen[ MainWin ] = routine_id( "onOpen_MainWin" )

-- event loop
WinMain( MainWin, Maximize )

-=-=-=-=-=-=-=-=-=-

Enjoy!

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu