6
\$\begingroup\$

I am attempting to write a game of blackjack using classes in Python. Any advice on keeping it DRY?

I seem to be creating too many lists in lists. Should I name the keys in the dictionary or just use integers? How can I get the deck, shuffle and deal logic into a class that will link with the Player class?

import random
import itertools as it
number_players = 2 #input('Enter Number of Players here: ')
number_cards = 2 #input('Enter Number of Cards here: ')
# create the deck of cards
deck = list(it.product("♠♣♥♦", [str(x) for x in range(2, 11)] + list("JQKA")))
times_to_shuffle_deck = 5
for x in range(times_to_shuffle_deck):
 random.shuffle(deck)
# print(len(deck))
# print(deck)
# init the memo
memo = set() 
def set_shuffle(n):
 for i in range(n):
 k = random.choice(deck)
 if k not in memo:
 memo.add(k)
 else:
 set_shuffle(1)
 return memo #sorted(memo)
i = set_shuffle(52)
def deal(deck, number_players, number_cards):
 """ 
 Deals n amount of cards to n amount of players.
 """
 player_dict = {'Player' + str(k + 1): [i.pop() for x in range(number_cards)] for k in range(number_players)}
 dealer_hand = [i.pop() for x in range(number_cards)]
 player_dict['Dealer'] = dealer_hand
 return player_dict
players = deal(deck, number_players, number_cards)
def print_current_cards(player_dict):
 """ pretty prints the current hands """
 for k, v in player_dict.items():
 print('{} hand:'.format(k))
 for u in v:
 print(u[1], u[0])
 print('\n')
print_current_cards(players)
class Player:
 """Takes in a players cards for processing"""
 def __init__(self, cards, player):
 self.cards = cards
 self.player = player
 def pic_to_int(self, card):
 """takes in a card and converts it to an integer of 10 for JQK or 10 and 11 for A """
 card_list = ['J', 'Q', 'K', '10']
 if card in card_list:
 return 10
 elif card == 'A':
 return 11
 if card not in card_list and card != 'A':
 return int(card)
 def current_score(self):
 """ Evaluates the current list of cards and returns a total integer value"""
 total = 0
 if self.is_blackjack() == True:
 return
 else:
 for c in self.cards:
 for c1 in c:
 for c2 in c1[1:]:
 if c2.isdigit():
 total += int(c2) 
 elif 'A' == c2:
 total += 11
 else:
 total += 10
 print('Current card total: ', total, '\n')
 return total
 def is_blackjack(self):
 """ Takes in 2 cards and returns True if the cards contain only 1x Ace and either 10, J, Q or K
 """
 if len(self.cards[0]) == 2:
 c1 = self.pic_to_int(self.cards[0][0][1])
 c2 = self.pic_to_int(self.cards[0][1][1])
 total = c1 + c2 if c1 or c2 else 0
 if total == 21:
 print('BLACKJACK!!!!')
 return 
 else:
 return False
 else:
 return False
 def check_if_bust(self):
 score = self.current_score()
 bust = False
 if score > 21:
 bust = True
 print("Bust!")
 return bust
 return bust
 def stick_or_twist(self, twist=False):
 """ Takes in current hand and processes a new card
 returns ok or bust
 """
 score = self.current_score()
 cards = self.cards
 if self.player == 'Dealer':
 if score < 17:
 cards[0].append(i.pop())
 self.check_if_bust()
 else:
 print('Dealer must stand on 17')
 elif self.player != 'Dealer':
 cards[0].append(i.pop())
 self.check_if_bust()
 def split_pair(self):
 """ splits a pair of the same cards into 2 games """
 pass
player1 = Player([v for k, v in players.items() if 'Player1' == k], 'Player1')
player2 = Player([v for k, v in players.items() if 'Player2' == k], 'Player2')
dealer = Player([v for k, v in players.items() if 'Dealer' == k], 'Dealer')
player_list = [player1, player2, dealer]
for p in player_list:
 print(p.player, ':')
 p.is_blackjack()
 p.current_score()
 p.check_if_bust()
 p.stick_or_twist(twist=True)
print(len(i), 'cards left')
print_current_cards(players)
# for x in range(3):
# j = i.pop()
# print(j)
# print(len(i), 'cards left')
asked Feb 17, 2018 at 2:41
\$\endgroup\$
0

1 Answer 1

2
\$\begingroup\$

In response to your question, a Deck class may look like this

class Deck():
 def __init__(self, times_to_shuffle_deck = 5):
 # create the deck of cards
 ...
 self.times_to_shuffle_deck = times_to_shuffle_deck
 def shuffle(self):
 # Here you can place code to shuffle
 def set_shuffle(self, n):
 # Here you can place function to set shuffle
 def deal(self, player, number_cards):
 # Here you could set a method to deal cards to a player
 # Probably less complex and easier to follow

Some minor recomendations:

-The class Player is doing a lot of work, you may consider extracting some methods outside, likepic_to_int or is_blackjack may go outside (not necessary in a class)

-The deal method I'd do shorter, since in that method you are creating something bigger than just dealing cards

  • When you pick this project in 3 months, and you want to create a player, you have to ask yourself which of this options is easier to remember:

    player1 = Player([v for k, v in players.items() if 'Player1' == k], 'Player1')
    player1 = Player('Player1')
    

So may be better to put fireworks with dict comprehensions inside the constructor

Regarding lists on lists and efficiency

In a blackjack game, roughly, you want to store

  • A list of all possible cards

  • A list of cards per player

  • A list of available cards (possible cards - player cards)

Then you can perform checks any way you want to discern player's points

You may want to try to design your app to have:

  • 1 possible_cards list + 1 available_cards list + n player_cards lists

If you think you're creating way too many lists, compare it with the minimum required and check where are you doing extra work

That was long.. Hope you spend some more time working on it

Don't hesitate to come back with more questions ;)

answered Feb 18, 2018 at 1:40
\$\endgroup\$
1
  • \$\begingroup\$ Thanks.. I have progressed somewhat and no doubt be back with more questions soon:) \$\endgroup\$ Commented Feb 18, 2018 at 4:42

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.