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')