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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.