ポートフォリオ用にRubyで作ったブラックジャックを自分でアップデートしてみた

初めに作ったブラックジャック↓↓
[Rubyでブラックジャック作ってみた（minitest使ってみた）](https://qiita.com/tsubasaman/items/6e2ccc5352904c163735)
### アップデートの内容
- １００万円稼いだら勝ち、所持金０円になったら負けというルールを追加。
- **play.rb(ゲーム起動クラス)**
    - ディーラーターンを同じ文で２箇所書いていたため、ディーラーターンメソッドを作り、よりコードを読みやすくした。
    - カードを引いたときのドキドキ感を増す為に、waitメソッドを作り、ディーラーがドローする前にEnterを押さないと進めないようにした。
    - 指定した金額をベットできるようにした。
- **card.rb（カードクラス）**
    - マークがわかりやすくなるように「スペード」「ハート」の、様にカタカナ表記を追加。

- **deck.rb（デッキクラス）**
    - プレイクラスを作った為、プレイヤーが毎回リセットされなくなった為、デッキをリセットできるように、リセットメソッドを作成した。
- **player.rb（プレイヤークラス）**
    - デッキクラスと同様プレイヤーが毎回初期化されなくなった為、テスト用に使っていたリセットメソッドをゲーム中にも使うようにした。
    - 「A」はバーストした際に「１」になるようにスコア計算メソッドに機能を追加。
    - ベット金額の計算機能を追加。
- **judge.rb（ジャッジクラス）**
    - 勝敗が決まったときのベットの計算機能を追加。
    - 所持金でゲームクリアかゲームオーバーかを判定する機能を追加。


- **test.rb（動作確認テスト）**
    - ベットの計算機能のテストを追加。
- **main.rb（ブラックジャックを動かすメインファイルだったが、プレイクラスを作った為、削除）**
### ルール
- 所持金が１００万以上で勝利。０円になったら敗北
- 「A」は「１」は都合良い数字に変換。というよりトータルスコアを変換。
- ヒットかスタンドのみ
- トータルスコアが高い方が勝ち
- ブラックジャック勝ちでベット金額３倍もらえる。通常２倍。


## play.rb(プレイクラス)
```play.rb
require './card'
require './deck'
require './judge'
require './money'
require './player'

class Play
    def initialize
        @player = Player.new
        @dealer = Player.new(name: 'ディーラー')
        play
    end

    def message(title, choice1="ヒット", choice2="スタンド") # win or lose or draw or error
        case title
        when :win
            puts 'あなたの勝ちです'
        when :lose
            puts 'あなたの負けです'
        when :draw
            puts '引き分けです'
        when :error
            puts '無効です。もう一度入力してください'
        when :choice
            puts "選択してください\s\sPush「 1 」→ #{choice1} 、Push「 2 」→ #{choice2}" 
        end
    end

    def dealer_turn
        # スタンド時の処理（ディーラーのターン）
        puts 'ディーラーのターンです'
        wait
        # プレイヤーがブラックジャックだった場合のディーラーの処理 
        if @player.blackjack?
            @dealer.draw
            @dealer.show
            if !@dealer.blackjack?
                message :win
                @player.money.stock = @player.bet_judge(@@bet, :blackjack)
                @player.money.show
                return
            else
                message :draw
                @player.money.stock = @player.bet_judge(@@bet, :draw)
                @player.money.show
                return
            end
        end
        # プレイヤーに勝つまでディーラーはヒットし続ける処理
        while true
            @dealer.draw
            @dealer.show
            wait
            if @dealer.burst?
                puts 'バースト！'
                message :win
                @player.money.stock = @player.bet_judge(@@bet, :win)
                @player.money.show
                break
            elsif @dealer.total_score == 21 && @player.total_score == 21
                message :draw
                @player.money.stock = @player.bet_judge(@@bet, :draw)
                @player.money.show
                break
            elsif @player.total_score < @dealer.total_score
                message :lose
                @player.money.stock = @player.bet_judge(@@bet, :lose)
                @player.money.show
                break
            end
        end
    end

    def bet_turn
        @player.money.show
        puts "いくらベットしますか？"
        while true
            bet = gets.to_i
            if bet < 1
                message :error
                redo
            elsif bet > @player.money.stock.to_i
                puts "賭け金が手持ち金額を上回っています。もう一度入力してください。"
                redo
            else
                puts <<~TEXT
                #{bet} 円ベットしました。
                #{'-' * 41}
                TEXT
                return bet
            end
        end
    end

    def play
        while true # 再プレイのためのループ処理
            # 手札リセット
            @player.reset
            @dealer.reset
            # 初ターンの処理
            puts "ようこそ、ブラックジャックへ"
            puts "ルール：手持ち資金が１００万円を超えたら勝ちです。０円になったら負けです。"
            puts "カードを配ります"
            @player.draw
            @player.draw
            @dealer.draw  
            @dealer.show
            @@bet = bet_turn
            @player.bet_calc(@@bet)
            @player.money.show
            # プレイヤーがブラックジャックじゃないか確認の処理
            if @player.blackjack?
                    puts "ブラックジャック！"
                    @player.show
            else
                @player.show
                message :choice
            end
            # ヒット、スタンドの処理（プレイヤーのターン）
            while true
                # ブラックジャックの場合は強制的にスタンドさせる処理
                if @player.blackjack?
                    command = 2
                else
                    command = gets.to_i # ヒットかスタンドか選択
                end
                # ヒットの場合の処理
                if command == 1
                    while true
                        @player.draw
                        if @player.burst? # バーストしていないか確認
                            @player.show
                            puts "バースト！！"
                            message :lose
                            @player.money.stock = @player.bet_judge(@@bet, :lose)
                            @player.money.show
                            break
                        end
                        # ドロー後のトータルスコアの確認
                        @player.show
                        # 最大値（２１）の場合は強制的にスタンドの処理
                        if @player.total_score == 21
                            puts 'トータルスコアが最大値に達しました'
                            command = 2
                            break
                        end
                        # 最大値ではない場合は、再度ヒットするか処理
                        puts "もう一度引きますか？"
                        message :choice
                        while true
                            command = gets.to_i # 再度、ヒットかスタンドの選択
                            if command == 1
                                break
                            elsif command == 2
                                break
                            else
                                message :error
                                redo
                            end
                        end
                        # ヒットかスタンドの処理
                        if command == 1 
                            redo
                        elsif command == 2
                            break
                        end
                    end
                    # バースト時の強制終了処理
                    if @player.burst?
                        break
                    end
                elsif command == 2
                    dealer_turn
                    command = nil
                    break
                else
                    # h,s以外が入力されたときの処理
                    message :error
                    redo
                end

                if command == 2
                    dealer_turn
                    break
                end

            end
            # ゲームオーバーか判定
            if @player.gameover?
                puts "所持金が０円になりました。"
                puts "ゲームオーバーです。"
                break
            elsif @player.win?
                puts "所持金が１００万円を超えました。"
                puts "あなたの勝ちです！！！！！！おめでとう！！！！！！！！！！！！"
                break
            end
            # 再プレイの処理
            puts "もう一回遊びますか？"
            message :choice, "遊ぶ", "遊ばない"
            while true
                command = gets.to_i # 再プレイするか選択
                if command == 1
                    command = nil
                    break
                elsif command == 2
                    break
                else
                    message :error
                    redo
                end
            end
            # 再プレイの処理

            command == nil ? redo : break
        end
    end

    def gameover

    end

    def wait(words='Enterキーを押してください')
        puts words
        c = gets
    end
end

Play.new
```

## card.rb(カードクラス)
```card.rb
class Card 
    attr_reader :mark, :number
    def initialize(mark, number)
        @mark   = mark.freeze
        @number = number.freeze
    end

    def convert
        if @number == 'J' || @number == 'Q' || @number == 'K' || @number == 'A'
            10
        else
            @number.to_i
        end
    end
end
```

## deck.rb(デッキクラス)
```deck.rb

class Deck
    attr_accessor :cards
    @@draw_count = 0

    def initialize
        @cards = []
        create
        @cards = @cards.shuffle
    end

    def create
        nums = ['A', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K']
        mark = ["❤ ハート\s\s\s\s", "♦︎ ダイヤ\s\s\s\s", "♤ スペード\s\s", "♧ クローバー"]
        mark.each do |m|
            nums.each do |n|
                @cards << Card.new(m, n)
            end
        end
    end

    def draw
        cards[@@draw_count]
    end

    def draw_count
        @@draw_count += 1
    end

    # テスト用のカード参照メソッド
    def show
        52.times do |n|
            puts "[ #{cards[n].mark} #{cards[n].number} ]"
        end
    end

    def reset
        @cards = @cards.shuffle
        @@draw_count = 0
    end
end

```

## player.rb(プレイヤークラス)
```player.rb

class Player
    include Judge
    attr_accessor :hands, :total_score, :name, :money
    @@deck = Deck.new
    def initialize(name: "プレイヤー")
        @hands = []
        @total_score = 0
        @name = name
        @money = Money.new
    end

    def draw
        self.hands << @@deck.draw
        self.total_score = self.total_score_calc
        @@deck.draw_count
    end

    
    def show
        hands = []
        self.hands.each do |hand|
            hands << "#{hand.mark} #{hand.number}"
        end
        puts "#{self.name}の手札です"
        puts hands
        puts  <<~TEXT
        #{puts "[ トータル  #{@total_score} ]"}
        -----------------------------------------
        TEXT
    end

    def a_count
        a = 0
        self.hands.each do |card|
            if card.number == 'A'
                a += 1
            end
        end
        a
    end
    
    def reset
        self.hands = []
        self.total_score = 0
        @@deck.reset
    end

    def total_score_calc
        @total_score = 0 # 複数回計算した場合に、加算しないように、毎回トータルスコアをリセットする
        self.hands.each do |hand|   # @numberに「A」があり、トータルスコアが２２以上ある場合、「A」の数だけ、トータルスコアから-9する。「A」の数をカウントするメソッドを作る。
            @total_score += hand.convert
        end
        if self.burst? && self.in_a?
            @total_score -= (self.a_count * 9)                # 「A」の数だけ、トータルスコアから-9する。「A」の数をカウントするメソッドを作る。
        end
        @total_score
    end

    def bet_calc(bet)
        self.money.stock  = self.money.stock.to_i - bet 
    end

    # テスト用メソッド

    def test
        puts "テストーーーーーー"
    end



    def reset_score
        self.total_score = 0
    end

    def in_blackjack
        self.hands << Card.new("♦︎", "J")
        self.hands << Card.new("♦︎", "A")
    end
end

# player = Player.new
# enemy  = Player.new
# player.draw
# player.draw
# enemy.draw
# enemy.draw
# player.hands
# player.total_score_calc
# enemy.total_score_calc
# p player.blackjack?
# p enemy.blackjack?

```

## judge.rb(ジャッジモジュール)
```judge.rb
module Judge

    def bet_judge(bet, judge)
        stock = self.money.stock
        case judge
        when :win
            stock += bet * 2
        when :lose
            stock += 0
        when :blackjack
            stock += bet * 3
        when :draw
            stock += bet
        end
    end

    def blackjack?
        if self.hands[1].number == "A" || self.hands[0].number == "A" 
            if  self.hands[0].number == "J" || self.hands[0].number == "Q"|| self.hands[0].number == "K" || \
                self.hands[1].number == "J" || self.hands[1].number == "Q"|| self.hands[1].number == "K"
                self.total_score = "ブラックジャック"
                true
            else
                false
            end
        else
            false
        end
    end

    def burst?
        self.total_score > 21 ? true : false
    end

    def in_a?
        self.hands.map do |card|
            if card.number == 'A'
                return true
            end
        end
        false
    end

    def gameover?
        self.money.stock <= 0 ? true : false
    end

    def win?
        self.money.stock > 1000000 ? true : false
    end

end
```

## test.rb(minitest)
```test.rb
require 'minitest/autorun'
require './card'
require './deck'
require './judge'
require './money'
require './player'
class BlackJackTest < Minitest::Test
    # テストカードのマークは「 ♦︎ 」で統一
    @@test_J      = Card.new('♦︎', 'J')
    @@test_Q      = Card.new('♦︎', 'Q')
    @@test_K      = Card.new('♦︎', 'K')
    @@test_A      = Card.new('♦︎', 'A')
    @@test_5      = Card.new('♦︎', 5)
    @@test_10     = Card.new('♦︎', 10)
    @@test_player = Player.new

    def test_blackjack?
        blackjack_player = Player.new
        blackjack_player.hands << @@test_A
        blackjack_player.hands << @@test_J
        assert blackjack_player.blackjack?

        blackjack_player.reset
        blackjack_player.hands << @@test_J
        blackjack_player.hands << @@test_A
        assert blackjack_player.blackjack?

        blackjack_player.reset
        blackjack_player.hands << @@test_Q
        blackjack_player.hands << @@test_A
        assert blackjack_player.blackjack?

        blackjack_player.reset
        blackjack_player.hands << @@test_A
        blackjack_player.hands << @@test_Q
        assert blackjack_player.blackjack?

        blackjack_player.reset
        blackjack_player.hands << @@test_A
        blackjack_player.hands << @@test_K
        assert blackjack_player.blackjack?

        blackjack_player.reset
        blackjack_player.hands << @@test_K
        blackjack_player.hands << @@test_A
        assert blackjack_player.blackjack?

        # false パターン
        # blackjack_player.reset
        # blackjack_player.hands << @@test_A
        # blackjack_player.hands << @@test_10
        # assert blackjack_player.blackjack?

        # blackjack_player.reset
        # blackjack_player.hands << @@test_5
        # blackjack_player.hands << @@test_5
        # assert blackjack_player.blackjack?

        # blackjack_player.reset
        # blackjack_player.hands << @@test_J
        # blackjack_player.hands << @@test_Q
        # assert blackjack_player.blackjack?
        

    end

    def test_burst?
        burst_player = Player.new
        burst_player.hands << @@test_J
        burst_player.hands << @@test_J
        burst_player.hands << @@test_5
        burst_player.total_score_calc
        burst_player.total_score
        assert burst_player.burst?
        # false
        # burst_player.reset
        # burst_player.hands << @@test_10
        # burst_player.total_score
        # assert burst_player.burst?
    end

    def test_total_score_calc
        total_score_calc_player = Player.new
        total_score_calc_player.hands << @@test_10
        total_score_calc_player.hands << @@test_5
        total_score_calc_player.total_score_calc
        assert_equal 15, total_score_calc_player.total_score
        total_score_calc_player.reset
        total_score_calc_player.hands << @@test_A
        total_score_calc_player.hands << @@test_10
        total_score_calc_player.hands << @@test_5
        total_score_calc_player.total_score_calc
        assert_equal 16, total_score_calc_player.total_score
        total_score_calc_player.reset
        total_score_calc_player.hands << @@test_A
        total_score_calc_player.hands << @@test_J
        assert_equal 20, total_score_calc_player.total_score_calc
        total_score_calc_player.hands << @@test_5
        assert_equal 16, total_score_calc_player.total_score_calc
        total_score_calc_player.hands << @@test_A
        assert_equal 17, total_score_calc_player.total_score_calc
        # false
        #assert_equal 10, total_score_calc_player.total_score
    end


    def test_convert
        assert_equal 10, @@test_J.convert
        assert_equal 10, @@test_Q.convert
        assert_equal 10, @@test_K.convert
        assert_equal 10, @@test_A.convert
        assert_equal 5, @@test_5.convert
    end

    def test_draw_count
        deck = Deck.new
        assert_equal 1, @@test_player.draw
        assert_equal 2, @@test_player.draw
        assert_equal 3, @@test_player.draw
    end


    def test_a_count
        a_player = Player.new
        a_player.hands << @@test_A
        a_player.hands << @@test_A
        a_player.hands << @@test_A
        assert_equal 3, a_player.a_count
    end

    def test_bet_calc
        #assert_equal 19000, @@test_player.bet_calc(1000)
        
    end

    def test_bet_judge
        p @@test_player.money.stock -= 250 # ベット
        assert_equal 20250, @@test_player.bet_judge(250,  :win)
        assert_equal 19750, @@test_player.bet_judge(250,  :lose)
        assert_equal 20500, @@test_player.bet_judge(250,  :blackjack)
        assert_equal 20000, @@test_player.bet_judge(250,  :draw)
    end

end

```