LoginSignup
1
1

More than 5 years have passed since last update.

ブラックジャック(一行でA処理版)

Last updated at Posted at 2019-03-04

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

のルールでチャレンジしてみたブラックジャック。
スコアの計算、Aの処理の部分は少し考えてみるとシンプルに。

スコアの計算

元ルールの処理:

JとQとKは10として扱う
Aはとりあえず「1」としてだけ扱う

    sc = sum(min(10, c.rank) for c in self)

拡張版:Aを1か11、有利な方でカウント

    if (sc <= 11 and 1 in [c.rank for c in self]): sc += 10

こちらの機能拡張も一行追加するのみ。

「Aは2枚以上11とカウントされない(22をオーバーしてしまう)」
⇒ 「全体スコアが11以下の時のみ、Aが11とカウントされる場合がある」
 と考えるとシンプルに。


改行入れてもソース全体で60行程度、Pythonは手軽に書きやすいなぁと思いました。
ブラウザで動かす版はこちら(colab)

BlackJack:ソース全体(改行込みで60行)

class Card: #カード:ユニコードでSuit表示
    SUITS = '♤♡♢♧'
    RANKS = '0 A 2 3 4 5 6 7 8 9 10 J Q K'.split()
    def __init__(self, suit, rank): self.suit, self.rank = suit, rank
    def __repr__(self): return f'{Card.SUITS[self.suit]}{Card.RANKS[self.rank]}'

import random
class Deck(list): #トランプの山
    def __init__(self):
        super().__init__([Card(suit, rank) for suit in range(4) for rank in range(1, 14)])
        random.shuffle(self)

class Hand(list):  # 手札
    @property
    def score(self):  # ブラックジャックのスコア(Bustした場合は負の数を返す)
        sc = sum(min(10, c.rank) for c in self)
        if (sc <= 11 and 1 in [c.rank for c in self]): sc += 10
        return sc if sc <= 21 else -sc

class Player: 
    def __init__(self, deck):
        self.deck = deck
        self.hand = Hand()
        self.draw()

    def __repr__(self): return (f"{self.__class__.__name__} {self.hand} :Score={self.hand.score}")

    def draw(self):
        self.hand.append(self.deck.pop())
        return self.hand.score

    def confirm_hit(self):
        view(self)
        return confirm('もう一枚引きますか?')

    def deal(self):
        while (self.draw() > 0):
            if (not self.confirm_hit()): return self.hand.score
        view(f"{self.__class__.__name__} の負け!バーストしました。 {self.hand} ")

class Dealer(Player):
    def confirm_hit(self): return self.hand.score < 17

def game():
    deck = Deck()
    dealer, player = Dealer(deck), Player(deck)
    view(dealer)
    if (player.deal() and dealer.deal()):
        view(dealer)
        if (player.hand.score >= dealer.hand.score):
            view('Playerの勝ちです。おめでとうございます!')
        else:
            view('Dealerの勝ちです。残念!')

def view(msg): print(msg)
def confirm(msg): return input(f'{msg} [y/n]').lower() == 'y'

if __name__ == '__main__':
    game()
    while confirm('もう一度ゲームしますか?'): game()




実行結果例

Dealer [♧4] :Score=4
Player [♧A, ♡K] :Score=21
もう一枚引きますか? [y/n]n
Dealer [♧4, ♧8, ♡4, ♢2] :Score=18
Playerの勝ちです。おめでとうございます!
もう一度ゲームしますか? [y/n]y
Dealer [♧7] :Score=7
Player [♧Q, ♤7] :Score=17
もう一枚引きますか? [y/n]n
Dealer [♧7, ♤4, ♢10] :Score=21
Dealerの勝ちです。残念!
もう一度ゲームしますか? [y/n]y
Dealer [♢A] :Score=11
Player [♢9, ♢J] :Score=19
もう一枚引きますか? [y/n]n
Dealer [♢A, ♤3, ♤K, ♢6] :Score=20
Dealerの勝ちです。残念!
もう一度ゲームしますか? [y/n]n

検討課題:

クラスや関数の名前、継承関係。GUI

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1