Python
ゲーム制作
アプリ開発
ブラックジャック

Pythonでブラックジャック作ってみた

はじめに

プログラミング入門者からの卒業試験は『ブラックジャック』を開発すべしに挑戦してみました

書き終わるまで他の人のコードは見てません
みなさんも開発する気があるなら見る前に書いてみることをおすすめします!

開発

開発するブラックジャックのルール

元記事のままです

  • 初期カードは52枚。引く際にカードの重複は無いようにする
  • プレイヤーとディーラーの2人対戦。プレイヤーは実行者、ディーラーは自動的に実行
  • 実行開始時、プレイヤーとディーラーはそれぞれ、カードを2枚引く。引いたカードは画面に表示する。ただし、ディーラーの2枚目のカードは分からないようにする
  • その後、先にプレイヤーがカードを引く。プレイヤーが21を超えていたらバースト、その時点でゲーム終了
  • プレイヤーは、カードを引くたびに、次のカードを引くか選択できる
  • プレイヤーが引き終えたら、その後ディーラーは、自分の手札が17以上になるまで引き続ける
  • プレイヤーとディーラーが引き終えたら勝負。より21に近い方の勝ち
  • JとQとKは10として扱う
  • Aはとりあえず「1」としてだけ扱う。「11」にはしない
  • ダブルダウンなし、スピリットなし、サレンダーなし、その他特殊そうなルールなし

開発してみて

元記事に書いてある通り、カードの柄と番号をどう扱うかがキモでした
私は上一桁を柄、下二桁を数字として
310 は 3 と 10 に分けてダイヤの 10 のように実装してみました
表示する際は辞書を使って変換します

コード

blackjack.py
from random import shuffle


SUIT = {
    1: 'ハート',
    2: 'スペード',
    3: 'ダイヤ',
    4: 'クローバー'
}

RANK = {
    1: 'A',
    11: 'J',
    12: 'Q',
    13: 'K'
}


class Deck:
    def __init__(self):
        self.deck = []
        for suit in range(1, 5):
            for rank in range(1, 14):
                self.deck.append(suit*100 + rank)
        shuffle(self.deck)

    def draw_card(self):
        return self.deck.pop()


class Participant:
    def __init__(self, name):
        self.name = name
        self.rank = []
        self.draw_card_history = []

    def get_sum(self):
        return sum(self.rank)

    def get_suit_rank(self, card):
        num_suit = card // 100
        num_rank = card % 100
        display_suit = SUIT[num_suit]
        display_rank = RANK.get(num_rank, str(num_rank))
        return num_suit, num_rank, display_suit, display_rank

    def set_hand(self, card, *, display=True):
        _, num_rank, display_suit, display_rank = self.get_suit_rank(card)
        if display:
            print('{} の引いたカードは {} の {} です'.format(self.name, display_suit, display_rank))
        else:
            print('{} の引いたカードはわかりません'.format(self.name))
        self.rank.append(min(num_rank, 10))
        self.draw_card_history.append(card)

    def over_twenty_one(self):
        if sum(self.rank) > 21:
            return True
        return False

    def display_suit_rank(self, n):
        card = self.draw_card_history[n-1]
        _, _, display_suit, display_rank = self.get_suit_rank(card)
        print('{} が引いた {} 枚目のカードは {} の {} です'.format(self.name, n, display_suit, display_rank))


class Player(Participant):
    def is_continue(self):
        print('{} のスコアは {}'.format(self.name, sum(self.rank)))
        if input('引く場合は y, やめる場合は n\n>') == 'y':
            return True
        return False


class Dealer(Participant):
    def is_continue(self):
        print('{} のスコアは {}'.format(self.name, sum(self.rank)))
        if self.get_sum() < 17:
            return True
        return False


def main():
    deck = Deck()
    player = Player('player')
    dealer = Dealer('dealer')

    player.set_hand(deck.draw_card())
    player.set_hand(deck.draw_card())
    dealer.set_hand(deck.draw_card())
    dealer.set_hand(deck.draw_card(), display=False)

    print()

    while player.is_continue():
        player.set_hand(deck.draw_card())
        if player.over_twenty_one():
            print('21 を越えました')
            print('あなたの負けです')
            break

    print()

    if not player.over_twenty_one():
        dealer.display_suit_rank(2)
        while dealer.is_continue():
            dealer.set_hand(deck.draw_card())

        if dealer.over_twenty_one() or player.get_sum() >= dealer.get_sum():
            print('あなたの勝ちです')
        else:
            print('あなたの負けです')


main()


実行画面

パターンは4つ

プレイヤーが21を超えたとき

image.png

プレイヤーが勝ったとき

image.png

ディーラーが21を超えたとき

image.png

ディーラーが勝ったとき

image.png

おわりに

今回は上記の開発に書いてある通りに開発してみました
またエラーとか全く調べてないので何か起こるかもしれませんし何か足りないかもしれません
今後細かいとこの見直し、色々な機能を追加を考えると楽しいですね
その前にブラックジャックのルールを覚えなきゃ、、、

追記(2018.07.25)

暇なときにちょこちょことやっています
GitHub