This question is from the book Daily Coding Problem, and is a slightly modified version of the problem described in the following MIT video. The question is as follows:
Blackjack is a two player card game whose rules are as follows:
For this problem, we simplify the card values to be as follows: each card between 2 and 10 counts as their face value, face cards count as 10, and aces count as 1.
Given perfect knowledge of the sequence of cards in the deck, implement a blackjack solver that maximizes the player's score (that is, wins minus losses).
The book has the following code:
import random
class Deck:
def __init__(self, seed=None):
self.cards = [i for i in range(1, 10)] * 4 + [10] * 16
random.seed(seed)
random.shuffle(self.cards)
def deal(self, start, n):
return self.cards[start:start + n]
class Player:
def __init__(self, hand):
self.hand = hand
self.total = 0
def deal(self, cards):
self.hand.extend(cards)
self.total = sum(self.hand)
def cmp(x, y):
return (x > y) - (x < y)
def play(deck, start, scores):
player = Player(deck.deal(start, 2))
dealer = Player(deck.deal(start + 2, 2))
results = []
for i in range(49 - start):
count = start + 4
player.deal(deck.deal(count, i))
count += i
if player.total > 21:
results.append((-1, count))
break
while dealer.total < 17 and count < 52:
dealer.deal(deck.deal(count, 1))
count += 1
if dealer.total > 21:
results.append((1, count))
else:
results.append((cmp(player.total, dealer.total), count))
options = []
for score, next_start in results:
options.append(score +
scores[next_start] if next_start <= 48 else score)
scores[start] = max(options)
def blackjack(seed=None):
deck = Deck(seed)
scores = [0 for _ in range(52)]
for start in range(48, -1, -1):
play(deck, start, scores)
return scores[0]Basically, for a suffix of the deck starting at card n (1 <= n <= 52), the code tries out all possibilities of the player taking 0 to 52 - n hits, until they go bust, and then the dealer taking hits as long as their score is <= 16.
For each iteration of the loop for i in range(49 - start), the count = number of cards used is reset to start + 4, which makes sense since we are simulating the player taking a different number of hits than last time. However, what troubles me is the player and the dealer's hands are not reset. In my mind, for each iteration of that loop, we should start with the player and dealer having been dealt two cards each, and not retain the last hand.
Am I understanding this right?