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







_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor

Reply via email to