I'm a new python developer and having trouble running a function on an object in a loop cleanly. I have an object class called Hand with a function hit.
def hit(self, Deck):
card = Deck.all_cards.pop(0)
self.card_list.append(card)
self.faces.append(str(card))
self.value = 0
for card in self.card_list:
self.value += card.value
# Ace Logic
aces = [card for card in self.card_list if card.rank == 'Ace']
for card in aces:
if self.value > 21:
self.value -= 10
This works as expected when called on a "one-off" basis.
I store the Hand object (inside a list) as a dictionary value.
I would then like to iterate through the dictionary and run the Hit function on each Hand object.
for plyr in game_dict:
game_dict[plyr][0].hit(deck)
The loop adds one card to the first Hand object but adds two cards to the second hand object. The second hand object is a copy of the first with an additional card.
Obviously I would like each Hand object to receive one card. I know I've fallen into some common OOP trap but I haven't been able to figure it out. Thanks.
Please see code:
#Global Vars
import random
suits = ('Hearts', 'Diamonds', 'Spades', 'Clubs')
ranks = ('Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten',
'Jack', 'Queen', 'King', 'Ace')
values = {'Two':2, 'Three':3, 'Four':4, 'Five':5, 'Six':6, 'Seven':7, 'Eight':8,
'Nine':9, 'Ten':10, 'Jack':10, 'Queen':10, 'King':10, 'Ace':11}
class Card:
'''Card object '''
def __init__(self, suit, rank):
self.suit = suit
self.rank = rank
self.value = values[rank]
def __str__(self):
return self.rank + ' of ' + self.suit
class Deck:
'''52 Card with four suits'''
def __init__(self):
self.all_cards = []
for suit in suits:
for rank in ranks:
# if values[rank] == 10: #split testing
# if rank in ['Ace']: #Ace logic testing
self.all_cards.append(Card(suit, rank))
def shuffle(self):
random.shuffle(self.all_cards)
def __str__(self):
return f'This deck has {len(self.all_cards)} cards.'
class Player:
'''
Player will be dealt cards and have following actions:
1.Hit (Recieve another card from deck)
2.Double down (Hit w/ bet x 2)
3.Stand (No change to hand)
4.Split (Turn one hand into two hands with SAME bet, respectively)
Attributes:
Name- Player Specified
Bet - Player Specified
Pot - Contains player's remaining betting capital
kwarg(s) - Hand objects
'''
def __init__(self, name, bet, pot=100, npc= True, **kwargs):
self.name = name
self.pot = pot
self.bet = bet
self.npc = npc
self.__dict__.update(kwargs)
def __str__(self):
return f'{self.name} has ${self.pot} to play.'
class Hand:
'''
Black jack hand used to track in-game attributes of hand
Attributes:
value - Integer of Black jack count
ordinal - Integer of hand creation order
face - list of card rank object
active - Boolean determination of in-game status
'''
def __init__(self, value=0, ordinal=1, card_list=[], faces=[], active=True):
self.value = value
self.ordinal = ordinal
self.card_list = card_list
self.faces = faces
self.active = active
# In game hit
def hit(self, Deck):
card = Deck.all_cards.pop(0)
self.card_list.append(card)
self.faces.append(str(card))
self.value = 0
for card in self.card_list:
self.value += card.value
# Ace Logic
aces = [card for card in self.card_list if card.rank == 'Ace']
for card in aces:
if self.value > 21:
self.value -= 10
def __str__(self):
cards = ','.join(self.faces)
if self.active == True:
status = 'Active'
else:
status = 'Inactive'
return f'This hand contains {cards} and is {status}.'
#Deck
deck = Deck()
deck.shuffle()
game_dict = {}
#Players
gambler = Player(name='Thomas', bet=25, pot=100, npc=False)
game_dict[gambler] = [Hand()]
npc_1 = Player(name='Phil', bet =25, pot=175)
game_dict[npc_1] = [Hand()]
for plyr in game_dict:
print(f'Player string: {plyr}')
print(f'Hand string: {game_dict[plyr][0]}')
game_dict[plyr][0].hit(deck)
print(f'Hand string: {game_dict[plyr][0]}')