Skip to content

Instantly share code, notes, and snippets.

@shiracamus
Last active April 28, 2018 03:40
Show Gist options
  • Save shiracamus/8c74cf6b97863c4ab56f607889cdfc1f to your computer and use it in GitHub Desktop.
Save shiracamus/8c74cf6b97863c4ab56f607889cdfc1f to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3.6
#-*- coding:utf-8 -*-
import sys
import random
from itertools import product
"""
開発するブラックジャックのルール
・初期カードは52枚。
・引く際にカードの重複は無いようにする
・プレイヤーとディーラーの2人対戦。
・プレイヤーは実行者、ディーラーは自動的に実行
・実行開始時、プレイヤーとディーラーはそれぞれ、カードを2枚引く。
引いたカードは画面に表示する。ただし、ディーラーの2枚目のカードは分からないようにする
・その後、先にプレイヤーがカードを引く。
プレイヤーが21を超えていたらバースト、その時点でゲーム終了
・プレイヤーは、カードを引くたびに、次のカードを引くか選択できる
・プレイヤーが引き終えたら、その後ディーラーは、自分の手札が17以上になるまで引き続ける
・プレイヤーとディーラーが引き終えたら勝負。より21に近い方の勝ち
・JとQとKは10として扱う
・Aは「1」あるいは「11」として扱う
・ダブルダウンなし、スピリットなし、サレンダーなし、その他特殊そうなルールなし
"""
class Card:
SUITS = ('Spade', 'Heart', 'Diamond', 'Club')
RANKS = ('A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K')
VALUES = {rank: (min(value, 10),) for value, rank in enumerate(RANKS, 1)}
VALUES['A'] = (1, 11)
def __init__(self, suit, rank):
self.suit = suit
self.rank = rank
self.value = Card.VALUES[rank]
def __repr__(self):
return f'{self.suit}-{self.rank}'
class Deck:
CARDS = [Card(suit, rank) for suit in Card.SUITS for rank in Card.RANKS]
def __init__(self):
self.cards = iter(random.sample(Deck.CARDS, len(Deck.CARDS)))
def next_card(self):
return next(self.cards)
class Player:
def __init__(self, name):
self.name = name
self.flush_cards()
def flush_cards(self):
self.cards = []
def hold(self, card):
self.cards.append(card)
def total(self):
values = map(sum, product(*(card.value for card in self.cards)))
return max(values, key=lambda value: value <= 21 and value or -value)
def value(self):
total = self.total()
return total <= 21 and total or 0
def hands(self):
cards = ' '.join(map(str, self.cards))
total = self.total()
busted_or_not = total > 21 and ' (busted)' or ''
return f'{self.name}: {cards}, Total={total}{busted_or_not}'
def want_to_draw(self, ask_to_draw):
return self.total() <= 21 and ask_to_draw(self)
class Dealer(Player):
def __init__(self, name):
super().__init__(name)
self.deck = Deck()
def deal_card_to(self, player):
try:
player.hold(self.deck.next_card())
except StopIteration:
self.deck = Deck()
player.hold(self.deck.next_card())
def deal_with(self, player, ui):
dealer = self
player.flush_cards()
dealer.flush_cards()
dealer.deal_card_to(player)
dealer.deal_card_to(dealer)
ui.show_hands(dealer) # show dealer's 1st card
dealer.deal_card_to(player)
dealer.deal_card_to(dealer)
while player.want_to_draw(ui.ask_to_draw):
dealer.deal_card_to(player)
while dealer.want_to_draw():
dealer.deal_card_to(dealer)
def want_to_draw(self):
return self.total() < 17 # 17以上になるまで引くルール
def judge_winner(self, player):
if self.value() > player.value():
return self
elif self.value() < player.value():
return player
else:
return None
class CharacterUserInterface:
def show(self, *message):
print(*message)
def show_hands(self, player):
print(player.hands())
def show_winner(self, player):
print(player and f'{player.name} win.' or 'Draw')
def ask(self, prompt):
while True:
answer = input(f'{prompt} [yes/no]: ').lower()
if 'yes'.startswith(answer):
return True
if 'no'.startswith(answer):
return False
if 'quit'.startswith(answer):
sys.exit()
print('Please input yes or no.')
def ask_to_draw(self, player):
self.show_hands(player)
return self.ask('Do you want to draw a card?')
def main(ui):
player = Player('You')
dealer = Dealer('Computer')
want_to_continue = True
while want_to_continue:
ui.show()
dealer.deal_with(player, ui)
ui.show()
ui.show_hands(player)
ui.show_hands(dealer)
ui.show_winner(dealer.judge_winner(player))
ui.show()
want_to_continue = ui.ask('Do you want to continue the game?')
if __name__ == '__main__':
main(CharacterUserInterface())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment