Created
March 30, 2017 15:52
-
-
Save jakab922/8dfd439b58be823a3258abae2675fc29 to your computer and use it in GitHub Desktop.
Command line blackjack game
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from random import shuffle, randint as ri | |
from itertools import product | |
PLAYER, OP, BOTH, NEITHER = range(4) | |
suits = ["clubs", "diamonds", "hearts", "spades"] | |
values = [ | |
"ace", "two", "three", "four", "five", | |
"six", "seven", "eight", "nine", "ten", | |
"jack", "queen", "king"] | |
class EmptyDeck(Exception): | |
pass | |
class Card(object): | |
def __init__(self, suit, value): | |
self.suit = suit | |
self.value = value | |
def __str__(self): | |
return "%s of %s" % (self.value, self.suit) | |
class DeckState(object): | |
def __init__(self): | |
self._cards = [ | |
Card(suit, value) for suit, value in | |
product(suits, values)] | |
shuffle(self._cards) | |
self._top = 51 | |
@property | |
def next(self): | |
if self._top < 0: | |
raise EmptyDeck() | |
self._top -= 1 | |
return self._cards[self._top + 1] | |
class PlayerState(object): | |
def __init__(self): | |
self.cards = [] | |
@property | |
def score(self): | |
cvalues = [0] | |
for card in self.cards: | |
if card.value == "ace": | |
lv = len(cvalues) | |
for i in xrange(lv): | |
cvalues.append(cvalues[i] + 11) | |
cvalues[i] += 1 | |
else: | |
i = values.index(card.value) | |
v = i + 1 if i < 10 else 10 | |
lv = len(cvalues) | |
for i in xrange(lv): | |
cvalues[i] += v | |
mv = min(cvalues) | |
if mv > 21: | |
return mv | |
best = cvalues[0] | |
for v in cvalues[1:]: | |
if v < 22 and v > best: | |
best = v | |
return best | |
def append(self, card): | |
self.cards.append(card) | |
class GameState(object): | |
def __init__(self): | |
self.state = BOTH | |
self.turn = PLAYER | |
def step(self, resign=False): | |
if self.turn == PLAYER: | |
if resign: | |
assert self.state in (BOTH, PLAYER) | |
if self.state == BOTH: | |
self.state = OP | |
else: | |
self.state = NEITHER | |
else: | |
if resign: | |
assert self.state in (BOTH, OP) | |
if self.state == BOTH: | |
self.state = PLAYER | |
else: | |
self.state = NEITHER | |
self.turn = (self.turn + 1) % 2 | |
class OpponentStrategy(object): | |
def __init__(self): | |
pass | |
def action(self, op_score, player_score): | |
if player_score > op_score and player_score < 22: | |
return True | |
if player_score > 21: | |
return False | |
elif op_score > 21: | |
return False | |
elif op_score < 11: | |
return True | |
else: | |
return ri(0, 10) < 21 - op_score | |
class Game(object): | |
def __init__(self): | |
self.deck_state = DeckState() | |
self.player = PlayerState() | |
self.opponent = PlayerState() | |
self.game_state = GameState() | |
self.opponent_strategy = OpponentStrategy() | |
def iter(self): | |
state = self.game_state.state | |
turn = self.game_state.turn | |
if state == NEITHER: | |
ps = self.player.score | |
os = self.opponent.score | |
print "Your final score is %s and the opponent's final score is %s\n" % (ps, os) | |
if ps < 22 and (ps > os or os > 21): | |
print "You won\n" | |
else: | |
print "You lost\n" | |
return False | |
elif state == BOTH: | |
if turn == PLAYER: | |
if self.player.score > 21: | |
self.game_state.step(True) | |
else: | |
choice = raw_input("Would you like to draw a card? (Y/n)\n") | |
if choice in ("", "y", "Y"): | |
card = self.deck_state.next | |
print "You drew a %s\n" % card | |
self.player.append(card) | |
self.game_state.step() | |
else: | |
self.game_state.step(True) | |
if turn == OP: | |
if self.opponent_strategy.action( | |
self.opponent.score, self.player.score): | |
card = self.deck_state.next | |
print "The opponent drew a %s\n" % card | |
self.opponent.append(card) | |
self.game_state.step() | |
else: | |
print "Your opponent resigned\n" | |
self.game_state.step(True) | |
elif state == PLAYER: | |
if turn == OP: | |
self.game_state.step() | |
else: | |
if self.player.score > 21: | |
self.game_state.step(True) | |
else: | |
choice = raw_input("Would you like to draw a card? (Y/n)\n") | |
if choice in ("", "y", "Y"): | |
card = self.deck_state.next | |
print "You drew a %s\n" % card | |
self.player.append(card) | |
self.game_state.step() | |
else: | |
self.game_state.step(True) | |
else: | |
if turn == PLAYER: | |
self.game_state.step() | |
else: | |
if self.opponent_strategy.action( | |
self.opponent.score, self.player.score): | |
card = self.deck_state.next | |
print "The opponent drew a %s\n" % card | |
self.opponent.append(card) | |
self.game_state.step() | |
else: | |
print "Your opponent resigned\n" | |
self.game_state.step(True) | |
return True | |
if __name__ == "__main__": | |
game = Game() | |
while game.iter(): | |
pass | |
exit() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment