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
toolic
14.6k5 gold badges29 silver badges204 bronze badges
asked Apr 2, 2024 at 12:26
\$\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.

answered Apr 2, 2024 at 14:45
\$\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.

answered Apr 2, 2024 at 13:25
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.