http://www.perlmonks.org?node_id=158720
Category: Fun Stuff
Author/Contact Info Steven Rubin (email, munchie.
Description: The classic pub game (what do I know about pubs, I'm 13!) Shut the Box, in a twelve number version (the original was 9 numbered). You roll 2 dice, and then you have a choice of putting individual numbers down, or combined numbers (Play the game to get used to it, I can't explain it very well). My dad gave me the suggestion, so that night, I cranked the original script out in less than an hour. There were 2 major bugs that annoyed me to death, so I left it sit for a couple weeks. Today, I came back to it and crushed those bugs flat (pardon my enthusiasm)! Enjoy!

UPDATE 1: Fixed code to change the redo FOO; to process_combos(); I also made it warnings compliant, which I was probably too ignorant to do in the beginning.

#! Perl -w
# shutthebox.pl -- classic game
use strict;
my($roll1, $roll2, $c1, @c2, @opts, $choice, $score, %pegs);
my $cnum="0";
my $endgame="0";
srand;
sub assign {
    foreach my $num ("1".."12") {
        $pegs{$num} = 1;
    }
}
sub show_board {
    print "\n\n";
    foreach my $num ("1".."12") {
        if ($pegs{$num}) {
            print "$num ";
        } else {
            print "# ";
        }
    }
    print "\n";
}
sub roll {
    print "Roll was: ";
    $roll1 = 1 + int rand(6);
    $roll2 = 1 + int rand(6);
    print "$roll1 and $roll2";
}
sub find_combos {
    $c1 = $roll1 + $roll2;
    @c2 = ($roll1, $roll2);
}
sub process_combos {
    $cnum = "0";
    @opts = undef;
    print "\nOptions: \n";
    if ($pegs{$c1}) {
        print "\t".++$cnum.") Put down $c1\n";
        $opts[$cnum] = $c1;
    }
    unless ($c2[0] == $c2[1]) {
        if ($pegs{$c2[0]} && $pegs{$c2[1]}) {
            print "\t".++$cnum.") Put down $c2[0] and $c2[1]\n";
            $opts[$cnum] = "13";
        }
    }
    foreach("1".."12"){
        unless (defined($pegs{$_})) {
            $endgame++;
        }
    }
    if ($endgame == 12){
        print "YOU WON!";
        exit;
    }
    unless($opts[1]) {
        print "\tnone\nYOU LOSE!\n";
        foreach my $left ("1".."12") {
            if ($pegs{$left}) {
                $score += $left;
            }
        }
        print "\tScore: $score (lower is best)";
        exit;
    }
    print "Which option? ";
    chomp($choice=<STDIN>);
    if ($opts[$choice] == $c1) {
        $pegs{$c1} = 0;
    } elsif ($opts[$choice] == 13 && $choice <= 2) {
        $pegs{$c2[0]} = 0;
        $pegs{$c2[1]} = 0;
    } else {
        print "Invalid option choice!\n";
        process_combos();
    }
}


assign();
while(1) {
    show_board();
    roll();
    find_combos();
    process_combos();
}
Replies are listed 'Best First'.
Re: Shut the Box : 12 Number Edition
by Jasper (Chaplain) on Apr 16, 2002 at 12:05 UTC
    I think it's more common practice to recursively call a subroutine, rather than label the whole thing in a block, and do a redo on that. i.e. replace redo FOO; with process_combos(); Apart from that, this is a very annoying game, that I suspect is very hard to win :)
Re: Shut the Box : 12 Number Edition
by Mr. Muskrat (Canon) on Apr 23, 2002 at 21:55 UTC
    Very nice. :)

    Add -w to the first line after perl
    Then run your program again. :)

    This is indeed a hard game to win.

    Matt

    Over a year later: Wow. My first write up.

      I've now made it work with warnings- I'm a little ticked off, because it took me forever and a day to win my first game of this (in real life), and then the first time my friend played it (again, in real life) he won! It's a very difficult game, but it's a good time waster.

      -munchie
      Look ma! I'm on CPAN!