3
\$\begingroup\$

This is code for a text-based game of Blackjack.

I would also like advice on how can I implement a betting system in this program. For example starting with an amount of chips and choosing how much of them to bet.

import random card_suit = ['Hearts', 'Diamonds', 'Clubs', 'Spades'] card_value = ['Ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King'] deck = [(value, suit) for suit in card_suit for value in card_value] def card_points(card): if card[0] in ['Jack', 'Queen', 'King']: return 10 elif card[0] == 'Ace': return 11 else: return int(card[0]) random.shuffle(deck) player_cards = [deck.pop(), deck.pop()] dealer_cards = [deck.pop()] player_points = sum(card_points(card) for card in player_cards) dealer_points = sum(card_points(card) for card in dealer_cards) def points(dealer_points, player_points, dealer_cards, player_cards): while dealer_points < 17: new_card = deck.pop() dealer_cards.append(new_card) dealer_points += card_points(new_card) print("Dealer's Cards:", dealer_cards) print("Dealer's Points:", dealer_points) print("\n") while True: print("Dealer's Cards:", dealer_cards) print("Dealer's Points:", dealer_points) print("\n") print("Player's Cards:", player_cards) print("Player's Points:", player_points) print("\n") decision = input('What will you do? ["hit" for a new card, "stand" to end the game]: ').lower() if decision == "hit": new_card = deck.pop() player_cards.append(new_card) player_points = sum(card_points(card) for card in player_cards) if player_points > 21: print("Dealer's Cards:", dealer_cards) print("Dealer's Points:", dealer_points) print("Player's Cards:", player_cards) print("Player's Points:", player_points) print("Dealer wins (player has more than 21 points)") break elif decision == "stand": while dealer_points < 17: new_card = deck.pop() dealer_cards.append(new_card) dealer_points += card_points(new_card) print("Dealer's Cards:", dealer_cards) print("Dealer's Points:", dealer_points) print("Player's Cards:", player_cards) print("Player's Points:", player_points) if player_points > 21: print("Dealer wins (player has more than 21 points).") elif dealer_points > 21: print("You win! (dealer has more than 21 points)") elif player_points > dealer_points: print("You win! (you have more points than the dealer)") elif player_points < dealer_points: print("Dealer wins (dealer has more points than the player).") else: print("It's a tie.") break else: print("Unknown input.") continue 
\$\endgroup\$
0

    2 Answers 2

    3
    \$\begingroup\$

    cryptic index

    deck = [(value, suit) for ... ] def card_points(card): if card[0] in ['Jack', 'Queen', 'King']: return 10 elif card[0] == 'Ace': 

    The tuples in that first line are very nice and pythonic. But this would have been even nicer:

    from collections import namedtuple Card = namedtuple('Card', 'value suit') deck = [Card(value, suit) for ... ] 

    Then later on we could speak of card.value without a cryptic [0] subscript.

    enum

    Consider defining class Value(Enum):, and moving the card_points() logic into that class. It is reasonable that a Jack object could display one way as a string yet also return 10 as a value.

    unicode cards

    The way you display cards is perfectly fine. It is worth noting that 52 unicode codepoints offer an alternate means of displaying them.

    common logic

    player_cards = [deck.pop(), deck.pop()] dealer_cards = [deck.pop()] player_points = sum(card_points(card) for card in player_cards) dealer_points = sum(card_points(card) for card in dealer_cards) 

    Consider defining class Hand:, and maintaining a list of Hands. Then indexing it gives you either the player or the dealer, and its .points() method gives you its total value.

    DRY

    Several times you print four items: {player,dealer} {cards,points}. Please extract a helper function.

    cite your reference

    The code should mention up top what game it implements. From the link in the Review Context I initially thought you meant standard blackjack, but this code implements a variant. I don't see any logic for Ace sometimes being worth 11 and sometimes 1.

    \$\endgroup\$
      2
      \$\begingroup\$

      Overview

      You've done a good job:

      • You leveraged code written by others with the import
      • Used meaningful names for many of the variables

      Here are some adjustments for you to consider, mainly for coding style.

      Layout

      I recommend moving the functions to the top, after the import. Having them in the middle of the code interrupts the natural flow of the code (from a human readability standpoint).

      Unused code

      I was about to recommend changing the name of the points function because it seemed too generic. However, I realized that it is not used, so it can be deleted.

      Documentation

      The card_points function always returns 11 for the Ace. The normal rules of Blackjack allow for the Ace to have a value of 1 in some circumstances.

      You should add documentation to describe whether or not the Ace can have a value of 1.

      Input

      It is great that you cast the user input into lower-case. It would also be helpful to allow the user to be lazy and just input h for "hit" or s for "stand".

      DRY

      These lines appear 3 times in the code:

       print("Dealer's Cards:", dealer_cards) print("Dealer's Points:", dealer_points) print("Player's Cards:", player_cards) print("Player's Points:", player_points) 

      You could add them into a new function, named something like show_cards, then call the function 3 times.

      \$\endgroup\$

        Start asking to get answers

        Find the answer to your question by asking.

        Ask question

        Explore related questions

        See similar questions with these tags.