1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Posted at

初めに作ったブラックジャック↓↓
Rubyでブラックジャック作ってみた(minitest使ってみた)

アップデートの内容

  • 100万円稼いだら勝ち、所持金0円になったら負けというルールを追加。

  • play.rb(ゲーム起動クラス)

    • ディーラーターンを同じ文で2箇所書いていたため、ディーラーターンメソッドを作り、よりコードを読みやすくした。
    • カードを引いたときのドキドキ感を増す為に、waitメソッドを作り、ディーラーがドローする前にEnterを押さないと進めないようにした。
    • 指定した金額をベットできるようにした。
  • card.rb(カードクラス)

    • マークがわかりやすくなるように「スペード」「ハート」の、様にカタカナ表記を追加。
  • deck.rb(デッキクラス)

    • プレイクラスを作った為、プレイヤーが毎回リセットされなくなった為、デッキをリセットできるように、リセットメソッドを作成した。
  • player.rb(プレイヤークラス)

    • デッキクラスと同様プレイヤーが毎回初期化されなくなった為、テスト用に使っていたリセットメソッドをゲーム中にも使うようにした。
    • 「A」はバーストした際に「1」になるようにスコア計算メソッドに機能を追加。
    • ベット金額の計算機能を追加。
  • judge.rb(ジャッジクラス)

    • 勝敗が決まったときのベットの計算機能を追加。
    • 所持金でゲームクリアかゲームオーバーかを判定する機能を追加。
  • test.rb(動作確認テスト)

    • ベットの計算機能のテストを追加。
  • main.rb(ブラックジャックを動かすメインファイルだったが、プレイクラスを作った為、削除)

ルール

  • 所持金が100万以上で勝利。0円になったら敗北
  • 「A」は「1」は都合良い数字に変換。というよりトータルスコアを変換。
  • ヒットかスタンドのみ
  • トータルスコアが高い方が勝ち
  • ブラックジャック勝ちでベット金額3倍もらえる。通常2倍。

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 "ルール:手持ち資金が100万円を超えたら勝ちです。0円になったら負けです。"
            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
                        # 最大値(21)の場合は強制的にスタンドの処理
                        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 "所持金が0円になりました。"
                puts "ゲームオーバーです。"
                break
            elsif @player.win?
                puts "所持金が100万円を超えました。"
                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」があり、トータルスコアが22以上ある場合、「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

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?