mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-23 07:29:02 -08:00
Merge pull request #419 from manminusone/44_Hangman
Perl implementation of Hangman
This commit is contained in:
223
44_Hangman/perl/hangman.pl
Executable file
223
44_Hangman/perl/hangman.pl
Executable file
@@ -0,0 +1,223 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
|
||||||
|
# global variables defined here
|
||||||
|
|
||||||
|
my(@WORDS) = qw(
|
||||||
|
GUM SIN FOR CRY LUG BYE FLY
|
||||||
|
UGLY EACH FROM WORK TALK WITH SELF
|
||||||
|
PIZZA THING FEIGN FIEND ELBOW FAULT DIRTY
|
||||||
|
BUDGET SPIRIT QUAINT MAIDEN ESCORT PICKAX
|
||||||
|
EXAMPLE TENSION QUININE KIDNEY REPLICA SLEEPER
|
||||||
|
TRIANGLE KANGAROO MAHOGANY SERGEANT SEQUENCE
|
||||||
|
MOUSTACHE DANGEROUS SCIENTIST DIFFERENT QUIESCENT
|
||||||
|
MAGISTRATE ERRONEOUSLY LOUDSPEAKER PHYTOTOXIC
|
||||||
|
MATRIMONIAL PARASYMPATHOMIMETIC THIGMOTROPISM
|
||||||
|
);
|
||||||
|
my(@PIC,$board,@guessedLetters,$guessCount,$hangCount);
|
||||||
|
my(%GUESSED);
|
||||||
|
|
||||||
|
# Subroutines defined here.
|
||||||
|
|
||||||
|
# init_variables: initialize all of the variables needed
|
||||||
|
# (this covers lines 50-90 in the original BASIC program)
|
||||||
|
|
||||||
|
sub init_variables {
|
||||||
|
@guessedLetters = ();
|
||||||
|
@PIC = (
|
||||||
|
'XXXXXXX ',
|
||||||
|
'X X ',
|
||||||
|
'X ',
|
||||||
|
'X ',
|
||||||
|
'X ',
|
||||||
|
'X ',
|
||||||
|
'X ',
|
||||||
|
'X ',
|
||||||
|
'X ',
|
||||||
|
'X ',
|
||||||
|
'X ',
|
||||||
|
'X ',
|
||||||
|
);
|
||||||
|
$guessCount = 0; %GUESSED = ();
|
||||||
|
$hangCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# addchar: given a row & column, put the specified char in that place in @PIC
|
||||||
|
sub addchar {
|
||||||
|
my($row,$col, $c) = @_;
|
||||||
|
|
||||||
|
substr($PIC[$row],$col,1) = $c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# main code starts here
|
||||||
|
|
||||||
|
print ' 'x31; print "Hangman\n";
|
||||||
|
print ' 'x14; print "Creative Computing Morristown, New Jersey\n\n\n\n";
|
||||||
|
|
||||||
|
# an iteration of the PLAY block is one complete game.
|
||||||
|
# There is a continue block that will ask if the user
|
||||||
|
# wants to play another game.
|
||||||
|
|
||||||
|
PLAY: while (1) {
|
||||||
|
|
||||||
|
init_variables();
|
||||||
|
# Any words left?
|
||||||
|
if (@WORDS == 0) {
|
||||||
|
print "You did all the words!\n";
|
||||||
|
last PLAY;
|
||||||
|
}
|
||||||
|
# splice a random word out of the @WORDS array
|
||||||
|
my($thisWord) = splice(@WORDS, int(rand(scalar @WORDS)),1);
|
||||||
|
# $board is the "game board" of the filled-out word
|
||||||
|
# that the user is working on
|
||||||
|
$board = '.'x(length $thisWord);
|
||||||
|
|
||||||
|
# GUESS loop is run for every time the user guesses a letter
|
||||||
|
GUESS: while(1) {
|
||||||
|
print "Here are the letters you used:\n";
|
||||||
|
printf("%s\n", join(',',@guessedLetters));
|
||||||
|
printf("\n\n%s\n", $board);
|
||||||
|
|
||||||
|
print "What is your guess for a letter ? ";
|
||||||
|
chomp(my $guess = <STDIN>);
|
||||||
|
# The %GUESSED hash allows us to quickly identify
|
||||||
|
# letters that have already been guessed
|
||||||
|
if ($GUESSED{lc $guess}) {
|
||||||
|
print "You guessed that letter before!\n\n";
|
||||||
|
redo GUESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
# save the guessed letter
|
||||||
|
push @guessedLetters, $guess;
|
||||||
|
$GUESSED{lc $guess} = 1;
|
||||||
|
++$guessCount;
|
||||||
|
|
||||||
|
# now look for the letter in the $thisWord var
|
||||||
|
# and put it into the $board var wherever it
|
||||||
|
# shows up. $foundLetter is a flag that indicates
|
||||||
|
# whether or not the letter is found.
|
||||||
|
my $foundLetter = 0;
|
||||||
|
for (my $i = 0; $i < length $thisWord; ++$i) {
|
||||||
|
if (lc substr($thisWord,$i,1) eq lc $guess) {
|
||||||
|
$foundLetter = 1;
|
||||||
|
substr($board, $i, 1) = substr($thisWord, $i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# The user found a letter in the solution!
|
||||||
|
if ($foundLetter) {
|
||||||
|
|
||||||
|
# Are there any '.' chars left in the board?
|
||||||
|
if (index($board, '.') < 0) {
|
||||||
|
print "You found the word!\n\n";
|
||||||
|
} else {
|
||||||
|
printf("%s\n\n", $board);
|
||||||
|
print "What is your guess for the word ? ";
|
||||||
|
chomp(my $guessword = <STDIN>);
|
||||||
|
if (lc $thisWord ne lc $guessword) {
|
||||||
|
print "Wrong. Try another letter.\n";
|
||||||
|
# Go to the next iteration of the GUESS loop
|
||||||
|
next GUESS;
|
||||||
|
}
|
||||||
|
printf("Right! It took you %d %s!\n", $guessCount, ($guessCount == 1 ? 'guess' : 'guesses'));
|
||||||
|
}
|
||||||
|
# At this point the user has discovered the word and won.
|
||||||
|
# This "next" statement takes execution down to the
|
||||||
|
# continue block for the PLAY loop;
|
||||||
|
next PLAY;
|
||||||
|
|
||||||
|
} else { # didn't find a letter
|
||||||
|
|
||||||
|
++$hangCount;
|
||||||
|
print "\n\n\nSorry, that letter isn't in the word.\n";
|
||||||
|
|
||||||
|
# The addchar() calls in the block below piece together the
|
||||||
|
# hangman graphic, depending on how many wrong letters
|
||||||
|
# the user has.
|
||||||
|
if ($hangCount == 1) {
|
||||||
|
print "First, we draw a head\n";
|
||||||
|
addchar(2,5,"-");addchar(2,6,"-");addchar(2,7,"-");
|
||||||
|
addchar(3,4,"("); addchar(3,5,"."); addchar(3,7,"."); addchar(3,8,")");
|
||||||
|
addchar(4,5,"-");addchar(4,6,"-");addchar(4,7,"-");
|
||||||
|
}
|
||||||
|
if ($hangCount == 2) {
|
||||||
|
print "Now we draw a body.\n";
|
||||||
|
for (5 .. 8) {
|
||||||
|
addchar($_, 6, "X");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($hangCount == 3) {
|
||||||
|
print "Next we draw an arm.\n";
|
||||||
|
for (3 .. 6) {
|
||||||
|
addchar($_, $_-1, "\\");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($hangCount == 4) {
|
||||||
|
print "This time it's the other arm.\n";
|
||||||
|
addchar(3,10, "/");
|
||||||
|
addchar(4, 9, "/");
|
||||||
|
addchar(5, 8, "/");
|
||||||
|
addchar(6, 7, "/");
|
||||||
|
}
|
||||||
|
if ($hangCount == 5) {
|
||||||
|
print "Now, let's draw the right leg.\n";
|
||||||
|
addchar( 9,5, "/");
|
||||||
|
addchar(10,4, "/");
|
||||||
|
}
|
||||||
|
if ($hangCount == 6) {
|
||||||
|
print "This time we draw the left leg.\n";
|
||||||
|
addchar(9,7,"\\");
|
||||||
|
addchar(10,8,"\\");
|
||||||
|
}
|
||||||
|
if ($hangCount == 7) {
|
||||||
|
print "Now we put up a hand.\n";
|
||||||
|
addchar(2,10,"\\");
|
||||||
|
}
|
||||||
|
if ($hangCount == 8) {
|
||||||
|
print "Next the other hand.\n";
|
||||||
|
addchar(2,2,"/");
|
||||||
|
}
|
||||||
|
if ($hangCount == 9) {
|
||||||
|
print "Now we draw one foot\n";
|
||||||
|
addchar(11,9,"\\");
|
||||||
|
addchar(11,10, "-");
|
||||||
|
}
|
||||||
|
if ($hangCount == 10) {
|
||||||
|
print "Here's the other foot -- you're hung!!\n";
|
||||||
|
addchar(11,2,"-");
|
||||||
|
addchar(11,3, "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("$_\n") for @PIC;
|
||||||
|
print "\n\n";
|
||||||
|
|
||||||
|
# Next guess if the user has not lost
|
||||||
|
if ($hangCount < 10) {
|
||||||
|
next GUESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Sorry, you lose. The word was %s\n", $thisWord);
|
||||||
|
next PLAY;
|
||||||
|
|
||||||
|
} # didn't find a letter block
|
||||||
|
} # GUESS block
|
||||||
|
} # PLAY block
|
||||||
|
|
||||||
|
# This block is reached either by the player winning (see the "next PLAY")
|
||||||
|
# statement) or by the user losing (as the PLAY block is complete and
|
||||||
|
# execution naturally comes to this continue block).
|
||||||
|
continue {
|
||||||
|
print "Want another word ? ";
|
||||||
|
chomp(my $in = <STDIN>);
|
||||||
|
if ($in !~ m/^y/i) {
|
||||||
|
# Exit the PLAY loop
|
||||||
|
print "\nIt's been fun! Bye for now.\n\n";
|
||||||
|
last PLAY;
|
||||||
|
}
|
||||||
|
# At this point execution goes to the start of the PLAY block,
|
||||||
|
# meaning a new game
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user