350 Besides keeping track of the `cards`, `Hand` should also keep track of the `value`. Under `self.cards`, create `self.value` and set it to 0. --- ```py class Hand: def __init__(self): self.cards = [] self.value = 0 ``` --- In this blackjack game, there will be a human-controled player and a program-controlled dealer. Add a `dealer` parameter in the `__init__` constructor method of the `Hand` class. When a `Hand` object is created, `dealer` should be set to `True` of `False` to keep track of what type of hand it is. --- ```py class Hand: def __init__(self, dealer): self.cards = [] self.value = 0 ``` --- Inside the `__init__` method, create a `self.dealer` variable and set it equal to the `dealer` parameter. --- ```py class Hand: def __init__(self, dealer): self.cards = [] self.value = 0 self.dealer = dealer ``` --- Function parameters can have default values. Change the parameters `(self, dealer)` to `(self, dealer=False)`. That code sets the default value of `dealer` to `False`. That means a `Hand` object can be constructed with or without passing in the value of `dealer`. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer ``` --- Now a `Hand` can be created. Let's give it some functionality. Add an `add_card` method. The method should take a `card_list` as a parameter. Inside the method, add `self.cards.extend(card_list)`. `extend` will append each item in the `card_list` list onto `cards` (`append` would append the full `card_list` list as a single item onto `cards`). --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) ``` --- Try out your code so far by adding the following lines of code to the bottom: ```py deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- Now add the ability to calculate the value of a hand. Add a method called `calculate_value` to `Hand`. Inside the method, set `self.value` to 0 since you will add all the values in the hand to this variable. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- Inside the `calculate_value` method, loop through each card in `self.cards` and get the value of the card. You can do that by adding the following code: ```py for card in self.cards: card_value = card.rank["value"] ``` --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 for card in self.cards: card_value = card.rank["value"] deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- `int()` is used to convert strings to integers. For example: `int("2")` will convert the string `"2"` to the integer `2`. Make sure `card.rank["value"]` is an integer by putting it inside `int()`. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 for card in self.cards: card_value = int(card.rank["value"]) deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- Just getting `card_value` for each card is not enough. Something must be done with that variable. The `+=` operator will add a value to a variable. For example: ``` num = 10 num += 5 ``` In the code above, `num` now equals 15. Inside the `for` loop, use the `+=` operator to add `card_value` to `self.value`. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- In blackjack, an Ace can have the value of either 11 or 1, depending on what is better for the player. First check if the hand has an Ace. Below `self.value = 0` create a variable called `has_ace` and set it to `False`. You don't need `self.` before the variable name since we will only use it in this method. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- --- NEW**** Add an if statement to check if hand has an ace, if so set has_ace to True ```py if card.rank["rank"] == "A": has_ace = True ``` After the last `for` loop you added, check `if has_ace and self.value > 21`. (Note: `if has_ace` means the same thing as `if has_ace == True`.) If the statement evaluates to true, use the `-=` operator to subtract 10 from `self.value`. (This program will not deal with the edge case of multiple Aces having a value of 1.) --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- Add another method to get the value of a hand called `get_value`. The function should return `self.value`. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): return self.value deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- Currently, the value that is returned could be incorrect. In the `get_value` method, before returning `self.value`, calculate the value first by calling `self.calculate_value()`. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- Create another method called `is_blackjack`. It should return `self.get_value() == 21`. That will be `True` if is a blackjack and `False` otherwise. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value def is_blackjack(self): return self.get_value() == 21 deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- Now you will create the final method in the `Hand` class that will display information about the hand. Create a method called `display` that will print "Your hand:". --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value def is_blackjack(self): return self.get_value() == 21 def display(self): print("Your hand:") deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- You can create a string by either surrounding text with single quotes (`'`) or double quotes (`"`). Whichever quote type you use, you can use the other quote type inside the string. If a string contains both single quotes and double quotes inside, you can surround it with `'''`. Change the print line you just added so it will print either "Dealer's hand:" or "Your hand:" by using this line of code: `print(f'''{"Dealer's" if self.dealer else "Your"} hand:''')`. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value def is_blackjack(self): return self.get_value() == 21 def display(self): print(f'''{"Dealer's" if self.dealer else "Your"} hand:''') deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- In the `display` method, add a `for` loop that prints out each card in `self.cards`. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value def is_blackjack(self): return self.get_value() == 21 def display(self): print(f'''{"Dealer's" if self.dealer else "Your"} hand:''') for card in self.cards: print(card) deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- If the player is not the dealer, it should print `"Value:", self.get_value()`. To check if something is not true, just add `not` before the thing you are checking. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value def is_blackjack(self): return self.get_value() == 21 def display(self): print(f'''{"Dealer's" if self.dealer else "Your"} hand:''') for card in self.cards: print(card) if not self.dealer: print("Value:", self.get_value()) deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- Now add an empty `print()` statement so a blank line will be printed. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value def is_blackjack(self): return self.get_value() == 21 def display(self): print(f'''{"Dealer's" if self.dealer else "Your"} hand:''') for card in self.cards: print(card) if not self.dealer: print("Value:", self.get_value()) print() deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.cards) ``` --- Change the last line of the program from `print(hand.cards)` to `print(hands.display())`. Then, run your program. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value def is_blackjack(self): return self.get_value() == 21 def display(self): print(f'''{"Dealer's" if self.dealer else "Your"} hand:''') for card in self.cards: print(card) if not self.dealer: print("Value:", self.get_value()) print() deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.display) ``` --- When the dealer's cards are printed during the game, only the second one should display. The first card should display as "hidden". In the `for` loop in the `display` method, you will need to get access to the card index since that will determine which to display. Update the first line of the `for` loop to `for index, card in enumerate(self.cards):` to get access to the card and index on each iteration of the loop. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value def is_blackjack(self): return self.get_value() == 21 def display(self): print(f'''{"Dealer's" if self.dealer else "Your"} hand:''') for index, card in enumerate(self.cards): print(card) if not self.dealer: print("Value:", self.get_value()) print() deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.display) ``` --- Put the `print(card)` line into an `if` statement. First check `index == 0 and self.dealer`. If that evaluates to true, print "hidden". If that evaluates to false, print the card. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value def is_blackjack(self): return self.get_value() == 21 def display(self): print(f'''{"Dealer's" if self.dealer else "Your"} hand:''') for index, card in enumerate(self.cards): if index == 0 and self.dealer: print("hidden") else: print(card) if not self.dealer: print("Value:", self.get_value()) print() deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.display) ``` --- At the end of a game, all the dealers cards should be shown. Add a parameter in the `display` method called `show_all_dealer_cards` and set the default value to `False`. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value def is_blackjack(self): return self.get_value() == 21 def display(self, show_all_dealer_cards=False): print(f'''{"Dealer's" if self.dealer else "Your"} hand:''') for index, card in enumerate(self.cards): if index == 0 and self.dealer: print("hidden") else: print(card) if not self.dealer: print("Value:", self.get_value()) print() deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.display) ``` --- Now add to the `if` statement so it only prints "hidden" if `show_all_dealer_cards` is not true. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value def is_blackjack(self): return self.get_value() == 21 def display(self, show_all_dealer_cards=False): print(f'''{"Dealer's" if self.dealer else "Your"} hand:''') for index, card in enumerate(self.cards): if index == 0 and self.dealer and not show_all_dealer_cards: print("hidden") else: print(card) if not self.dealer: print("Value:", self.get_value()) print() deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.display) ``` --- Add one final check to the `if` statement to check if is not a blackjack (`self.is_blackjack()`). --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value def is_blackjack(self): return self.get_value() == 21 def display(self, show_all_dealer_cards=False): print(f'''{"Dealer's" if self.dealer else "Your"} hand:''') for index, card in enumerate(self.cards): if index == 0 and self.dealer and not show_all_dealer_cards and not self.is_blackjack(): print("hidden") else: print(card) if not self.dealer: print("Value:", self.get_value()) print() deck = Deck() deck.shuffle() hand = Hand() hand.add_card(deck.deal(2)) print(hand.display) ``` --- You are done creating the `Hand` class so delete all the code under the `Hand` class that was used for testing. --- ```py class Hand: def __init__(self, dealer=False): self.cards = [] self.value = 0 self.dealer = dealer def add_card(self, card_list): self.cards.extend(card_list) def calculate_value(self): self.value = 0 has_ace = False for card in self.cards: card_value = int(card.rank["value"]) self.value += card_value if has_ace and self.value > 21: self.value -= 10 def get_value(self): self.calculate_value() return self.value def is_blackjack(self): return self.get_value() == 21 def display(self, show_all_dealer_cards=False): print(f'''{"Dealer's" if self.dealer else "Your"} hand:''') for index, card in enumerate(self.cards): if index == 0 and self.dealer and not show_all_dealer_cards and not self.is_blackjack(): print("hidden") else: print(card) if not self.dealer: print("Value:", self.get_value()) print() ``` --- PART THREE (final part) IS HERE: https://gist.github.com/beaucarnes/c42904ba7a7bf0e8688791f6e0e97716