convenientstore has asked for the wisdom of the Perl Monks concerning the following question:

I been trying to understand below program.. But I cannot get past the concept of couple areas,
1)
foreach $i (0..$#letters) { if ($blankword[$i]) { print $blankword[$i]; } else { print "-"; }
Say @letters = n o w, and iterating over 0..$#letters would assign i to $letters[0]=n $letters1=o $letters2=w and @blankword was 0 0 0, how is $blankword\$i\ is one of n o w ???

2)can someone please explain to me in plain english what
$guesses[@guesses]=$guess;

I guess @guesses=() was intially to empty array, now, how does
above mean? assigning $guess word to @guesses array, but not sure what putting array in square bracket means(never seen it before)
#!/usr/bin/perl -w @words = qw( internet answers printer program ); @guesses=(); $wrong=0; $choice=$words[rand @words]; $hangman="0-|--<"; @letters=split(//, $choice); @hangman=split(//, $hangman); @blankword=(0) x scalar(@letters); OUTER: while ($wrong<@hangman) { foreach $i (0..$#letters) { if ($blankword[$i]) { print $blankword[$i]; } else { print "-"; } } print "\n"; if ($wrong) { print @hangman[0..$wrong-1] } print "\n Your Guess: "; $guess=<STDIN>; chomp $guess; foreach(@guesses) { next OUTER if ($_ eq $guess); } $guesses[@guesses]=$guess; $right=0; for ($i=0; $i<@letters; $i++) { if ($letters[$i] eq $guess) { $blankword[$i]=$guess; $right=1; } } $wrong++ if (not $right); if (join('', @blankword) eq $choice) { print "You got it right!\n"; exit; } } print "$hangman\nSorry, the word was $choice.\n";

Replies are listed 'Best First'.
Re: hangman question
by GrandFather (Saint) on Jul 15, 2007 at 23:25 UTC

    $#letters is the index of the last element in @letters (or -1 if there are no elements). $blankword[$i] accesses the element at index $i of @blankword. The loop foreach $i (0..$#letters) {...} prints each of the known letters in the word and prints a '-' for any unknown letters. The if ($blankword[$i]) tests to see if a letter is known or unknown by testing to see if the element is zero or not.

    In scalar context @array returns the number of elements in @array (cf $#array above). So $guesses[@guesses]=$guess; assigns $guess to the next unused element in @guesses. It would be more Perlish to push @guesses, $guess instead.


    DWIM is Perl's answer to Gödel
      Hey, thanks for your reply. Further questions on your explanation..
      previsouly, "@blankword" was 0 0 0 (let's say for 3 letter words.. say like ---> n o w

      so going through (0..$#letters), $i gets assigned n
      o
      w
      now, how does $blankwordn equals element is zero or not?

        No. $i gets assigned 0, 1 and 2 - indexes into the two arrays, not the contents of the elements of @letters. 0 .. $#letters is the list context range operator and generates a list containing the integers from 0 to the index of the last element in @letters (0, 1 and 2 for this example).

        The code depends on elements of @blankwords being set to 0 until they are assigned a correct letter. The test could be rewritten if ($blankword[$n] eq $letters[$i]) { to make an explicit check that the correct letter has been guessed.


        DWIM is Perl's answer to Gödel
Re: hangman question
by ysth (Canon) on Jul 16, 2007 at 00:40 UTC
    2)can someone please explain to me in plain english what
    $guesses[@guesses]=$guess;
    @guesses is in scalar context there, so it produces the number of elements in the array. That is used as an index to assign to an element of the array. Since the pre-assignment elements are numbered 0 through (@guesses - 1), it adds a new element to the end of the array.

    A much clearer way to write it would be:

    push @guesses, $guess;
      There is at least one case where the construct
      $guesses[@guesses]=$guess;
      makes sense, which is when you want the new element to autovivify. You can say
      $guesses[@guesses]->{ key} = 'value';
      to create a hashref in the new place. With push() you'll have to create the hash yourself.

      Anno