After see this old article of making a perfect maze generation (tile based version) in PHP I tried to translate the original PHP code to Ruby. After a few tries, I can’t see where I’m making a mistake.
Here’s my Ruby code:
maze_width = 9
maze_height = 7
moves = []
width = 2*maze_width +1
height = 2*maze_height +1
maze = Hash.new{|h, k| h[k] = []}
for x in 0..height-1
for y in 0..width-1
maze[x][y] = 1
end
end
x_pos = 1
y_pos = 1
maze[x_pos][y_pos] = 0
moves.push(y_pos + (x_pos * width))
while(!moves.empty?)
possible_directions = ""
# puts "x_pos: #{x_pos} y_pos: #{y_pos}"
if(maze[x_pos+2][y_pos]== 1 and x_pos+2!=0 and x_pos+2!=height-1)
possible_directions += "S"
end
if(maze[x_pos-2][y_pos]== 1 and x_pos-2!=0 and x_pos-2!=height-1)
possible_directions += "N"
end
if(maze[x_pos][y_pos-2]== 1 and y_pos-2!=0 and y_pos-2!=width-1)
possible_directions += "W"
end
if(maze[x_pos][y_pos+2]== 1 and y_pos+2!=0 and y_pos+2!=width-1)
possible_directions += "E"
end
if(!possible_directions.empty?)
move = rand(possible_directions.length)
case(possible_directions[move].chr)
when "N":
maze[x_pos-2][y_pos] = 0;
maze[x_pos-1][y_pos] = 0;
x_pos -= 2;
when "S":
maze[x_pos+2][y_pos] = 0;
maze[x_pos+1][y_pos] = 0;
x_pos += 2;
when "W":
maze[x_pos][y_pos-2] = 0;
maze[x_pos][y_pos-1] = 0;
y_pos -= 2;
when "E":
maze[x_pos][y_pos+2] = 0;
maze[x_pos][y_pos+1] = 0;
y_pos += 2;
end
moves.push(y_pos+(x_pos*width))
else
back = moves.pop
x_pos = (back/width).floor
y_pos = back%width
end
end
# draw the maze
for x in 0..height-1
for y in 0..width-1
print((maze[x][y] == 1) ? "#" : " ")
end
puts
end
If I execute that, it shows a ugly and non perfect maze:
###################
# # #
# # #
#
## # #
# # #
# # #
#
# #
# #
## # #
# # #
# #
#
###################
This is really different from the PHP output:
###################
# # # #
### # # ##### ### #
# # # # # # # #
# # # ### # ### ###
# # # # # #
# # ### ##### ### #
# # # # #
# ### ########### #
# # # # #
# # ### ####### # #
# # # # # #
# ####### # # ### #
# # #
###################
When translating code between languages, beware of nit-picky semantic differences. The one that’s biting you here is that negative indexes in Ruby count back from the end of the array, rather than returning null. The maze code doesn’t have any range checks to see if
x_posory_posare moving off the end of the array; it just relies on the array returning null if asked for nonexistent elements. The end result is that you’re allowing moves off the left and top and getting nonsensical results.You’ll also get nil exceptions going off the right and bottom if the randomizer hits right, so you want checks on those, too.
So, on the four directional checks, add some range code. e.g, turn this:
into this:
and likewise for the
y_posones andwidth.