Last active
April 28, 2018 03:40
-
-
Save shiracamus/8c74cf6b97863c4ab56f607889cdfc1f to your computer and use it in GitHub Desktop.
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
#!/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