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

Well, if you read my original post, then i was all wrong about the problem. The real problem was in sub score when i called score again to evaluate the player/dealers score after a ace was changed from worth 11 to worth 1. Thanks Fever for noticing that the problem had nothing to do with the original score call in sub dealtwo. Well now, with the updated code there is another problem. I get a deep recursion (more then 100 calls of a subroutine from itself) error when i run this and the hand sub score is evaluating has an ace in it. In case you dont know the format of the cards it is suit space card, so 10 of hearts would be h 10. there might be a problem with the regex in sub score. Thanks again, all suggestions welcome!
#!/usr/bin/perl -w use strict; my (%def, %value, @deck, @playerhand, @dealerhand); ##### # define the symbols for each card and each cards value ##### %def = ( "h" => "hearts", "c" => "clubs", "d" => "diamonds", "s" => "spades", "j" => "jack", "q" => "queen", "k" => "king", "a" => "ace", # ace with a value of 11 "1" => "ace" # ace with a value of 1 ); foreach ( 1 .. 10, qw/ j q k a / ) { if ( !/[j, q, k, a]/ ) { $value{$_} = $_; } elsif ( /a/ ) { $value{$_} = 11; } else { $value{$_} = 10; } } ##### # create the deck, shuffle it, and then deal the first hand ##### createdeck( \@deck ); shuffledeck( \@deck ); for (0 .. 1) { push @playerhand, shift @deck; push @dealerhand, shift @deck; } dealtwo( \%def, \@deck, \@playerhand, \@dealerhand, \%value ); ##### # the main dealing routine ##### sub dealtwo { my ($def, $deck, $playerhand, $dealerhand, $value) = @_; my ($hos, $score, $card); print "You were dealt:\n"; foreach ( @$playerhand ) { /^(\w) (\w+)$/i; if ( exists $$def{$2} ) { # since not all possible cards ar +e in %def, if it isn't print it straight $card = $$def{$2}; } else { $card = $2 } print " " . $card . " of " . $$def{$1} . "\n"; } $score = score( $playerhand, 0, $value ); print "Your are showing: " . $score . "\n\n"; print "\nThe dealer was dealt:\n"; $$dealerhand[0] =~ /^(\w) (\w+)$/i; # only show one card of the de +alers hand until the player is done if ( exists $$def{$2} ) { $card = $$def{$2}; } else { $card = $2 } print " " . $card . " of " . $$def{$1} . "\n"; $score = score( $dealerhand, 1, $value ); print "He is showing: " . $score . "\n\n"; print "Hit or Stay?"; $_=<>; chomp; if (/h/i) { push @$playerhand, shift @$deck; dealtwo($def, $deck, $playerhand, $dealerhand, $value); # anot +her "hit or stay" for player } else { end($def, $deck, $playerhand, $dealerhand, $value); # call the + dealer logic } } ##### # shuffle deck (fisher yates) ##### sub shuffledeck { my ($deck) = @_; my ($i, $j); for ($i = @$deck; --$i; ) { $j = int rand ($i+1); next if $i == $j; @$deck[$i,$j] = @$deck[$j,$i]; } } ##### # create deck ##### sub createdeck { my ($deck) = @_; my ($i, $j); foreach $i ( qw/ h d c s / ) { foreach $j ( 2 .. 10, qw/ j q k a / ) { push @$deck, "$i $j"; } } } ##### # calculate the score, and do some win/lose logic ##### sub score { my ($hand, $dop, $value) = @_; # $dop says wether to return 1 + or all cards, 0 for player my ($score, $ace, $i); # 1 for dealer in sub dealtwo +and 2 for dealer in sub end $ace = 0; # weher foreach (@$hand) { /^(\w) (\w+)$/i; $ace=1 if $2 eq "a"; $score += $$value{$2}; } if ($score > 21 and $ace == 1) { #lines in question for ($i = @$hand; --$i;) { #lines in questi +on @$hand[$i] =~ s/^(\w) a$/$1 1/i; #lines in question } score( $hand, $dop, $value ); } if ($score > 21 and $dop == 0 and $dop != 2) { lose($score); exit(); } if ($score == 21 and $dop == 0 and $dop != 2 ) { win($score); exit(); } if ($score < 21 and $#$hand == 5 ) { win2($score); exit(); } @$hand[0] =~ /^(\w) (\w+)$/i; if ( $dop == 1 ) { return $$value{$2}; } else { return $score; } } ##### # player loses ##### sub lose { my ($score) = @_; print "Your are showing: " . $score . "\n"; print "You lose!" } ##### # player wins ##### sub win { my ($score) = @_; print "Your are showing: " . $score . "\n"; print "You win!" } ##### # player wins by having 5 cards under 21 ##### sub win2 { my ($score) = @_; print "Your are showing: " . $score . " and have 5 cards!\n"; print "You win!" } ##### # dealer subroutine ##### sub end { my ($def, $deck, $playerhand, $dealerhand, $value) = @_; my ($score, $card); $score = score( $dealerhand, 2, $value ); print "\nThe dealer was dealt:\n"; foreach ( @$dealerhand ) { /^(\w) (\w+)$/i; if ( exists $$def{$2} ) { $card = $$def{$2}; } else { $card = $2 } print " " . $card . " of " . $$def{$1} . "\n"; } print "He is showing: " . $score . "\n\n"; while ( $score < 17 ) { #if the dealers score is + less then 17 then hit print "The dealer hits!\n"; push @$dealerhand, shift @$deck; $score = score( $dealerhand, 2, $value ); print "\nThe dealer was dealt:\n"; foreach ( @$dealerhand ) { /^(\w) (\w+)$/i; if ( exists $$def{$2} ) { $card = $$def{$2}; } else { $card = $2 } print " " . $card . " of " . $$def{$1} . "\n"; } print "He is showing: " . $score . "\n\n"; } print "The deal stays!\n\n"; if ($score > score( $playerhand, 2, $value ) and $score < 22) { lose( score( $playerhand, 2, $value ) ); } elsif ($score < score( $playerhand, 2, $value ) ) { win( score( $playerhand, 2, $value ) ); } elsif ($score == score( $playerhand, 2, $value ) ) { print "You are showing " . score( $playerhand, 2, $value ) . +"\n"; print "You push!"; exit(); } elsif ($score > 21) { print "You win,the dealer is over 21\n"; } }

Replies are listed 'Best First'.
Re: Blackjack problems (multiple reference passes et al)
by BeernuT (Pilgrim) on Feb 17, 2002 at 19:31 UTC
    you might try adding
    use warnings; use diagnostics;
    might help you understand the problem a little better

    -bn
      oh, thanks. i did have warnings on, i must have turned it off for some reason before posting. I am not sure what diagnostics is, but i will look it up and see if i cant get this working
Re: Blackjack problems (multiple reference passes et al)
by I0 (Priest) on Feb 18, 2002 at 00:56 UTC
    if ($score > 21 and $ace == 1) { #lines in question for ($i = @$hand; $i--;) { #lines in quest +ion last if $$hand[$i] =~ s/^(\w) a$/$1 1/i; #lines in quest +ion } $score = score( $hand, $dop, $value ); }
Re: Blackjack problems (multiple reference passes et al)
by TippyTurtle (Novice) on Feb 18, 2002 at 04:53 UTC
    I got totally bored so I converted what was orginally posted to OO, perhaps not the neatest, but what the heck.
    My line count is higher, but I created methods for almost everything despite the stability or lack of reuse of several of the parts. I was just wasting time. In that same vain I am aware there are modules to create decks of cards and/or deal them, I just found the exercise fun.

      Can't locate object method "no_winner" via package "BlackJack" at - line 298, <> line 1.