Maze Maker
I remember when I was in school, I used to play the game where you help the mouse go through the maze and reach the target as quickly as possible. Even
when I finished my college, I would still wonder how one can create a maze. Those who create maze must be super ingenious.
It was only recently I decided to decode the mystery of maze creation. I asked my friend Google and guess what, I was presented with plenty of solutions in various languages. Some very difficult to follow and some not so difficult. Having got my head around the algorithm, I decided to do it in my first language i.e. Perl. It didn’t took me long to convert the algorithm into Perl script.
As you all know, I am still a new player in Raku. Thankfully I have plenty of support when it comes to Raku queries. For the first time, I decided to be part of Raku Advent Calendar. Thanks to JJ Merelo, I was given a slot. At that point, I didn’t have a clue what I am going to do. But I knew I have plenty of ideas that can be converted into Raku.
As you guessed it correctly, I picked my favourite maze maker script for the Raku Advent Calendar. With the help of many people on Twitter, I got my first draft ready in Raku. But it wasn’t creating the tunnel as expected. I went to my friend, Scimon Proctor, for guidance. He helped me with the Raku magic and all working smoothly now.
It was time to do some housekeeping before I hand it over to JJ Merelo. Having spent around 30 minutes, I got my final draft ready as below:
use v6;
my %opposite-of = ( 'north' => 'south', 'south' => 'north', 'west' => 'east', 'east' => 'west' );
my @directions = %opposite-of.keys;
sub MAIN(Int :$height = 10, Int :$width = 10) {
my $maze;
make-maze( 0, 0, $maze, $height, $width );
say render-maze( $maze, $height, $width );
}
#
#
# METHODS
sub make-maze( $x, $y, $maze is rw, $height, $width ) {
for ( @directions.pick(@directions) ) -> $direction {
my ( $new_x, $new_y ) = ( $x, $y );
if ( 'east' eq $direction ) { $new_x += 1; }
elsif ( 'west' eq $direction ) { $new_x -= 1; }
elsif ( 'south' eq $direction ) { $new_y += 1; }
else { $new_y -= 1; }
if not-visited( $new_x, $new_y, $maze, $height, $width ) {
$maze[$y][$x]{$direction} = 1;
$maze[$new_y][$new_x]{ %opposite-of{$direction} } = 1;
make-maze( $new_x, $new_y, $maze, $height, $width );
}
}
}
sub not-visited( $x, $y, $maze, $height, $width ) {
# check the boundary
return if $x < 0 or $y < 0;
return if $x > $width - 1 or $y > $height - 1;
# return false if already visited
return if $maze[$y][$x];
# return true
return 1;
}
sub render-maze($maze, $height, $width) {
my $as_string = " " ~ ( "_ " x $width );
$as_string ~= "\n";
for ( 0 .. $height - 1 ) -> $y {
$as_string ~= "|";
for ( 0 .. $width - 1 ) -> $x {
my $cell = $maze[$y][$x];
$as_string ~= $cell<south> ?? " " !! "_";
$as_string ~= $cell<east> ?? " " !! "|";
}
$as_string ~= "\n";
}
return $as_string;
}
What next?
I am thinking of converting this into a Raku Library, something like Games::Maze. I am working on it, hopefully I should have it ready before Christmas.
If you think it can be improved in any way then please do share with me. I would love to hear from you and learn from your experience. Till then have fun with it from a Perl Fan, who equally loves Raku.
I can’t wait to try it out!
LikeLike