#!/usr/bin/perl use Getopt::Std; use strict; =pod =head1 NAME coffee 2002 - A command line random number guessing game. =head1 SYNOPSYS ./coffee-2002 -h ./coffee-2002 [-c] [-m #] [max_rand_num] =head1 DESCRIPTION This version was written to fill 30 minutes of my spare time after bumping into the original coffee.pl that I wrote in 1997, when I was first learning Perl. I saw that the original had a serious problem in the loop that created the random number (if you can call a game serious) and decided to write a "modern" coffee game. As for the name and concept of "The Coffee Game", I got it from a program my Dad had in the late 70's. It was the same basic game running on a pile of circuitry that he built by hand. When I started programming, I thought this an apropos tribute to my upbringing. =head1 AUTHOR Rodney Broom R.Broom Consulting, http://www.rbroom.com/ =head1 CHANGES =over 4 =item 2002-04-17 - Initial writing, have fun. =item 2003-04-04 - Fixed several spelling errors and typos. - Made the random number generation work on MS Windows. =back =cut my $opt = {}; my $opt_ok = getopts('chm:', $opt); my $MAX_NUM = 100; my $MAX_RAND_TRIES = 5; if ($opt->{h} or not $opt_ok) { print qq{ USAGE $0 [OPTIONS] [max_num] OPTIONS c Cheat Turn on cheating messages. h Help Show this message. m Max random tries By default we'll only try $MAX_RAND_TRIES times to create a random number. If for some reason it takes more tries than that, we'll quit with an error message. You can force this number higher by passing a positive integer with the -m switch. This is a random number guessing game. You get told in the begining the range of numbers that the random number could fall in, then have to guess what the number might be. With each guess, we'll tell you if you are low or high. By default, the numbers range from 1 to $MAX_NUM, but you may pass a new max number to use as an argument. To quit, type a 'q' instead of a number. Rodney Broom R.Broom Consulting, http://www.rbroom.com/ }; exit $opt_ok ? 0 : 1; } ## ## Set up the configuration ## my $cheating = $opt->{c}; if ($opt->{m}) { if ($opt->{m} =~ /^(\d+)$/ and $1 > 0) { $MAX_RAND_TRIES = $opt->{m}; } else { die qq{Invalid max random tries passed, must be a positive integer.\n}; } } if ($ARGV[0]) { if ($ARGV[0] =~ /^(\d+)$/ and $1 > 0) { $MAX_NUM = $ARGV[0]; } else { die qq{Invalid max number passed, must be a positive integer.\n}; } } ## ## Play the game ## print qq{***\n*** Coffee game - 2002\n***\n\n}; print qq{Building random number from 1 to $MAX_NUM... }; my $random = gen_rand($MAX_NUM); printf qq{Got it%s.\n}, $cheating ? qq{ (Pst, it's $random)} : ''; my $entry; my $guess; while (1) { $guess = prompt(qq{Take a guess: }, $cheating ? $random : undef); if ($guess =~ /^q$/i) { print qq{Thank you for playing, the number was $random.\n}; exit 0; } elsif ($guess =~ /^\d+$/) { if ($guess < $random) { print qq{Too low, guess again.\n}; } elsif ($guess > $random) { print qq{Too high, guess again.\n}; } else { my $answer = prompt(qq{That's right, play again? (y/n)}, 'n'); if ($answer =~ /^y/i) { print qq{Glad to hear it, here we go.\n}; $random = gen_rand($MAX_NUM); } else { print qq{Glad to have had you, please coma again.\n}; exit 0; } } } else { print qq{Invalid entry, please try again.\n}; } } sub prompt { my $msg = shift; my $def = shift; printf qq{$msg%s}, $def ? qq{ [$def] } : ''; chomp(my $answer = ); $answer ||= $def; return $answer; } sub gen_rand { my $max = shift; # My Win98 does a REALLY bad job of number generation. This was my work # around. if ($^O =~ /^MSWin/) { my $seed = time/12345678; $seed =~ s/\.....(.....).*$/$1/; srand($seed); } else { srand($$ + time); } my $rand; my $tries = 0; # This will usually only take one try. until ($rand > 0) { $rand = int(rand($max+1)); die qq{Too many tries at creating a random number.\n} if ++$tries > $MAX_RAND_TRIES; } return $rand; }