SelfTaught
SelfTaught

Reputation: 499

Unexpected values in hash?

I'm trying to create a maze generator and I'm having some trouble with my code. At the beginning of my script, I create a multidimensional array (@maze) with X number of columns and Y number of rows. There is a loop which iterates through the array and sets all of the elements to an initial value of 1. The get_neighbors sub routine is suppose to create a hash with top, right, bottom, left keys. It then sets the values for these keys based on the x and y coords which get passed in. For the top key, I set it's value to the element directly above which should be [ $y - 1 ][ $x ]. I was assuming that if for example, the coords, 0, 0 were passed in, top would be set to undef since that's not a valid element / position, but it's not.. It's being set to 1. Not sure why.. Was hoping someone could spot and explain why that's happening. Here's the entire script:

#!/usr/bin/perl

use warnings;
use strict;
use Switch;
use Data::Dumper;

# Rows is set equal to the first arg passed in
# unless it hasn't been. If it hasn't been, the
# value defaults to 60. This also applies to the
# columns.
my $rows  = (defined($ARGV[ 0 ]) ? $ARGV[ 0 ] : 60);
my $cols  = (defined($ARGV[ 1 ]) ? $ARGV[ 1 ] : 60);
my $cells = $rows * $cols;

my @maze;

# "Pre-allocate" each "Cell" for the maze.
for(my $y = 0; $y < $rows; ++$y) {
    for(my $x = 0; $x < $cols; ++$x) { $maze[ $y ][ $x ] = 1; }
} 

# Run 
main();

#--------------------------
# Main ~
#--------------------------
sub main {
    print Dumper(get_neighbors(0, 0));

    generate();
    print_maze();   

    return;
}

#--------------------------
# Generate the maze w/ BFS
#--------------------------
sub generate {

    return;
}

#--------------------------
# Print maze to console
#--------------------------
sub print_maze {
    for(my $y = 0; $y < $rows; ++$y) {
        for(my $x = 0; $x < $cols; ++$x) {
            print $maze[ $y ][ $x ] . " ";
        }
        print "\n";
    }
}

#--------------------------
# Returns the values of 
# neighboring cells 
#--------------------------
sub get_neighbors {
    my $x = shift;
    my $y = shift;

    my %neighbors;

    $neighbors{'top'}    = defined($maze[ $y - 1 ][ $x ]) ? $maze[ $y - 1 ][ $x ] : undef; 
    $neighbors{'bottom'} = defined($maze[ $y + 1 ][ $x ]) ? $maze[ $y + 1 ][ $x ] : undef;
    $neighbors{'left'}   = defined($maze[ $y ][ $x - 1 ]) ? $maze[ $y ][ $x - 1 ] : undef;
    $neighbors{'right'}  = defined($maze[ $y ][ $x + 1 ]) ? $maze[ $y ][ $x + 1 ] : undef;

    return %neighbors;
}

The out when I run this script is:

# perl mazegen.pl 10 10
$VAR1 = 'left';
$VAR2 = 1;
$VAR3 = 'right';
$VAR4 = 1;
$VAR5 = 'top';
$VAR6 = 1;
$VAR7 = 'bottom';
$VAR8 = 1;
1 1 1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 1 1 

Upvotes: 0

Views: 70

Answers (2)

shawnhcorey
shawnhcorey

Reputation: 3601

Try:

$neighbors{ top    } = $y > 0              ? $maze[ $y - 1 ][ $x ] : undef;
$neighbors{ bottom } = $y < $#maze         ? $maze[ $y + 1 ][ $x ] : undef;
$neighbors{ left   } = $x > 0              ? $maze[ $y ][ $x - 1 ] : undef;
$neighbors{ right  } = $x < $#{ $maze[0] } ? $maze[ $y ][ $x + 1 ] : undef;

Upvotes: 0

Jim Davis
Jim Davis

Reputation: 5290

In Perl, a negative subscript on an array counts from the end of the array.

For example:

my @foo = ('a', 'b', 'c', 'd', 'e');

say $foo[-2];

would display d.

This should illustrate what's happening:

use warnings;
use strict;
use feature 'say';

my @maze = ( [ 'a' .. 'e' ],
             [ 'f' .. 'j' ],
             [ 'k' .. 'o' ],
             [ 'p' .. 't' ],
             [ 'u' .. 'y' ], );

for my $row (@maze) {
    say "@$row";
}

my %neighbors;
my ($x, $y) = (0, 0);

# The // defined-or was added in Perl 5.10.  These are equivalent:
# $foo = defined($bar) ? $bar : 'toast';
# $foo = $bar // 'toast';

$neighbors{'top'}    = $maze[ $y - 1 ][ $x ] // '-'; 
$neighbors{'bottom'} = $maze[ $y + 1 ][ $x ] // '-';
$neighbors{'left'}   = $maze[ $y ][ $x - 1 ] // '-';
$neighbors{'right'}  = $maze[ $y ][ $x + 1 ] // '-';

say "  $neighbors{top}";
say "$neighbors{left} $maze[$y][$x] $neighbors{right}";
say "  $neighbors{bottom}";

Output:

a b c d e
f g h i j
k l m n o
p q r s t
u v w x y
  u
e a b
  f

Upvotes: 2

Related Questions