[Tutor] Blackjackbetting
Dave Angel
davea at ieee.org
Mon Jul 4 17:00:32 CEST 2011
On 01/-10/-28163 02:59 PM, David Merrick wrote:
> HI. I feel I'm starting to go round in circles solving this problem. I feel
> I made significant progress.
> Can someone help me iron out the bugs please
>
> # Blackjack
> # From 1 to 7 players compete against a dealer
>
> import cards, games
>
> class BJ_Card(cards.Card):
> """ A Blackjack Card. """
> ACE_VALUE = 1
>
> @property
> def value(self):
> if self.is_face_up:
> v = BJ_Card.RANKS.index(self.rank) + 1
> if v> 10:
> v = 10
> else:
> v = None
> return v
>
> class BJ_Deck(cards.Deck):
> """ A Blackjack Deck. """
> def populate(self):
> for suit in BJ_Card.SUITS:
> for rank in BJ_Card.RANKS:
> self.cards.append(BJ_Card(rank, suit))
>
>
> class BJ_Hand(cards.Hand):
> """ A Blackjack Hand. """
> def __init__(self, name):
> super(BJ_Hand, self).__init__()
> self.name = name
>
> def __str__(self):
> rep = self.name + ":\t" + super(BJ_Hand, self).__str__()
> if self.total:
> rep += "(" + str(self.total) + ")"
> return rep
>
> @property
> def total(self):
> # if a card in the hand has value of None, then total is None
> for card in self.cards:
> if not card.value:
> return None
>
> # add up card values, treat each Ace as 1
> t = 0
> for card in self.cards:
> t += card.value
>
> # determine if hand contains an Ace
> contains_ace = False
> for card in self.cards:
> if card.value == BJ_Card.ACE_VALUE:
> contains_ace = True
>
> # if hand contains Ace and total is low enough, treat Ace as 11
> if contains_ace and t<= 11:
> # add only 10 since we've already added 1 for the Ace
> t += 10
>
> return t
>
> def is_busted(self):
> return self.total> 21
>
> class Bet(object):
> """ A Blackjack Gamble. """
> # Values
> def __init__(bet, money = 10):
> stash = money
>
> # Betting options
> def betting(bet,stash):
> try:
> if stash> 0:
> wager = int(input("\nHow much do you want to wager?: "))
> if wager> stash:
> int(input("\n You can only wager what you have. How
> much?: "))
> elif wager< 0:
> int(input("\n You can only wager what you have. How
> much?: "))
> except ValueError:
> int(input("\n That's not valid! Choose a number: "))
>
>
> # Money Conditions
> def gamble(bet):
> if bet.stash<= 0:
> print("\nYou are out of money! You're out of the game!")
>
>
>
> class BJ_Player(BJ_Hand):
> """ A Blackjack Player. """
> stash = 10
> if stash<= 0:
> print("\nYou are out of money! You're out of the game!")
>
> def is_hitting(self):
> response = games.ask_yes_no("\n" + self.name + ", do you want a hit?
> (Y/N): ")
> return response == "y"
>
> def bust(self,stash,wager):
> print(self.name, "busts.")
> self.lose(self,stash,wager)
>
> def lose(self,stash,wager):
> print(self.name, "loses.")
> stash = stash - wager
> print("Your stash is: ",stash)
> return stash
>
> def win(self,stash,wager):
> print(self.name, "wins.")
> stash = stash + wager
> print("Your stash is: ",stash)
> return stash
>
> def push(self):
> print(self.name, "pushes.")
>
>
> class BJ_Dealer(BJ_Hand):
> """ A Blackjack Dealer. """
> def is_hitting(self):
> return self.total< 17
>
> def bust(self):
> print(self.name, "busts.")
>
> def flip_first_card(self):
> first_card = self.cards[0]
> first_card.flip()
>
>
> class BJ_Game(object):
> """ A Blackjack Game. """
> def __init__(self, names):
> self.players = []
> for name in names:
> stash = 100
> player = BJ_Player(name)
> playerbet = Bet(stash).betting(stash)
> self.players.append(player)
>
> self.dealer = BJ_Dealer("Dealer")
>
> self.deck = BJ_Deck()
> self.deck.populate()
> self.deck.shuffle()
>
> @property
> def still_playing(self):
> sp = []
> for player in self.players:
> if not player.is_busted():
> sp.append(player)
> return sp
>
> def __additional_cards(self, player,stash,wager):
> while not player.is_busted() and player.is_hitting():
> self.deck.deal([player])
> print(player)
> if player.is_busted():
> player.bust(self,stash,wager)
>
> def play(self,stash,wager):
> # deal initial 2 cards to everyone
> self.deck.deal(self.players + [self.dealer], per_hand = 2)
> self.dealer.flip_first_card() # hide dealer's first card
> for player in self.players:
> print(player)
> print(self.dealer)
>
> # deal additional cards to players
> for player in self.players:
> self.__additional_cards(player,stash,wager)
>
> self.dealer.flip_first_card() # reveal dealer's first
>
> if not self.still_playing:
> # since all players have busted, just show the dealer's hand
> print(self.dealer)
> else:
> # deal additional cards to dealer
> print(self.dealer)
> self.__additional_cards(self.dealer,stash,wager)
>
> if self.dealer.is_busted():
> # everyone still playing wins
> for player in self.still_playing:
> player.win(stash,wager)
> else:
> # compare each player still playing to dealer
> for player in self.still_playing:
> if player.total> self.dealer.total:
> player.win(stash,wager)
> elif player.total< self.dealer.total:
> player.lose(stash,wager)
> else:
> player.push()
>
> # remove everyone's cards
> for player in self.players:
> player.clear()
> self.dealer.clear()
>
>
> def main():
> print("\t\tWelcome to Blackjack!\n")
> stash = 0
> wager = 0
> names = []
> number = games.ask_number("How many players? (1 - 7): ", low = 1, high =
> 8)
> for i in range(number):
> name = input("Enter player name: ")
> names.append(name)
> print()
>
> game = BJ_Game(names)
>
> again = None
> while again != "n":
> game.play(stash,wager)
> again = games.ask_yes_no("\nDo you want to play again?: ")
>
>
> main()
> input("\n\nPress the enter key to exit.")
>
> *Output*
>
> Welcome to Blackjack!
>
> How many players? (1 - 7): 1
> Enter player name: Dave
>
>
> How much do you want to wager?: 50
> Dave: Qc 8s (18)
> Dealer: XX 3d
>
> Dave, do you want a hit? (Y/N): n
> Dealer: Kd 3d (13)
> Dealer: Kd 3d Qh (23)
> Traceback (most recent call last):
> File "I:/Python/Python Source Code/chapter09/blackjackBettingB.py", line
> 229, in<module>
> main()
> File "I:/Python/Python Source Code/chapter09/blackjackBettingB.py", line
> 225, in main
> game.play(stash,wager)
> File "I:/Python/Python Source Code/chapter09/blackjackBettingB.py", line
> 188, in play
> self.__additional_cards(self.dealer,stash,wager)
> File "I:/Python/Python Source Code/chapter09/blackjackBettingB.py", line
> 166, in __additional_cards
> player.bust(self,stash,wager)
> TypeError: bust() takes exactly 1 positional argument (4 given)
>
It would appear from your filenaming that this program orginally came
from some book. Do you actually understand the version that the book
used (which presumably worked) ?
Have you tried to analyze this program, to clean it up? it'd be nice to
know which parts were already there and which parts you added. Are you
perhaps working from the book "Python Programming for the Absolute
Beginner" by Dawson?
If I had to tackle this one blind, without its history, I'd start by
making a diagram of the classes involved. You have BJ_Player derived
from BJ_Hand, which is another way of saying that a player is a kind of
hand. That makes no sense, so the code in those classes will make no
sense. It's not as clear whether a BJ_Dealer should be a kind of
player. Also, if you're working from the above book, Deck is already
derived from Hand.
Inheritance usually expresses a "is a" kind of relationship. So a
Black-jack card is a card, a Black-jack deck is a deck.
On the other hand, instance attributes express a "has a" kind of
relationship. A player has a hand, not is a hand. So the hand should
should be an attribute of the player.
Assuming that's the book you're using, why do you duplicate the populate
method in BJ_Deck, when the base class already has the same code?
Why does a BJ_Hand need a name attribute? Shouldn't a name be an
attribute of a player? I think this is a side effect of pretending that
a player is a hand.
I can't figure out what the Bet class is all about.
The BJ_Player class starts with a class attribute stash. But presumably
you should have a separate stash for each player. Where's the __init__
method? That's presumably where you should associate a name and stash
with a particular player?
In BJ_Game.play(), you call player.win(), passing stash in. But stash
is a simple local, so its value is shared among all players.
And so on. You need to figure out what each class is going to be, which
ones have 'is a' relationships, and which ones have 'has a'
relationships. Then you need to decide what each class instance is
going to store, and make sure it's done explicitly in the __init__ for
that class. If there's some reason the __init__() can't initialize one
of its values, then put a comment there, listing it at least. And
while you're learning, you should avoid having four symbols with the
same name, but having different scopes, lifetimes, and purposes. For
example, 'stash'.
Some of these suggestions are already contradicted by the book you're
using. For example, a Deck knows how to deal to a list of hands. But
you have a list of players which shouldn't be the same thing. There are
various ways of solving that.
DaveA
More information about the Tutor
mailing list