Home > Back-end >  How to update a counter from dictionary Python
How to update a counter from dictionary Python

Time:01-03

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.

CodePudding user response:

Python ints are immutable, this means dealer_points isn't updated. Initialy they have the same id(use id()), but when you change the variable inside the function it creates a new variable. To fix your code you need to do something like

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]
    return point_selection

dealer_points = deal_initial_cards(dealer_hand, dealer_points)
print(dealer_points)

whereas a list, which you probably noticed, is mutable. This means the list inside the function stays the same(keeps its id) even when its edited.

CodePudding user response:

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)
  • Related