Search code examples
pythoncounter

How to update a counter from dictionary Python


I'm new to Python and coding in general and am trying to create a blackjack game in Python but I'm having trouble getting the point counter point_selection to update based on the card values in the player's hand:

deck_points = {2 : 2, 3 : 3, 4 : 4, 5 : 5, 6 : 6, 7 : 7, 8 : 8, 9 : 9, 10 : 10, 'J' : 10, 'Q' 
: 10, 'K' : 10, 'A' : 11 }

dealer_hand = []
player_hand = []

dealer_points = 0
player_points = 0

def deal_initial_cards(hand, point_selection):
    for i in range(2):
        i = random.choice(list(deck_points))
        hand.append(i)
    for card in hand:
        point_selection += deck_points[card]

deal_initial_cards(dealer_hand, dealer_points)
print(dealer_points)

Using the above code, the counter never updates past '0' and I'm not sure what I'm doing wrong. Any help is appreciated.


Solution

  • Here's a more Pythonic solution that fixes your main bug about your function deal_initial_cards() operating on a copy of its (immutable) int argument point_selection then throwing away the result, since it doesn't have a return point_selection (or store the result in a class member self.points). (Also, I made all your dict keys strings: '2','3',.... It's usually customary to represent '10' as 'T' to make all cards a single letter).

    But since you're essentially declaring a Hand class, then instantiating two objects of it (dealer_hand, player_hand). deal_initial_cards() is essentially a Hand._init__() in disguise, so we have a data member cards (best not to also call it hand). See how simple and clean ph = Hand() is; no need for globals. Moreover, we could statically compute points inside the __init__() function and return it (or, better, store it in self.points inside each hand object), but that would be a bad decomposition, since if we subsequently add cards to self.cards, points wouldn't get updated. So, much more Pythonic is to make points a property of the class. We then access it without parentheses: dh.points, not dh.points(). Last, note the use of a list comprehension (instead of a for-loop-append) to generate self.hand. And inside points(), note the use of a generator expression deck_points[card] for card in self.cards, again more Pythonic than for-loop counter. So this small example is a great showcase of Python idiom and decomposition. We can add a __str__() method to Hand. (You could also have a Card class, but really that would be overkill.)

    import random
    
    deck_points = {'2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, 'T': 10, 'J' : 10, 'Q'
    : 10, 'K' : 10, 'A' : 11 }
    
    # No globals, so no need to initialize anything
    
    class Hand:
    
        def __init__(self):
            self.cards = [random.choice(list(deck_points)) for _ in range(2)]
    
        @property
        def points(self):
            return sum(deck_points[card] for card in self.cards)
    
        def __str__(self, join_char=''):
            return join_char.join(card for card in self.cards)
    
    #deal_initial_cards(dealer_hand, dealer_points)
    ph = Hand()
    dh = Hand()
    print('Dealer: ', end='')
    print(dh.points)
    print('Player: ', end='')
    print(ph.points)