rubyでブラック・ジャックできるんです!!

今日はこちらの記事を参考にしてトランプのブラック・ジャックを作ってみました。

仕様

・初期カードは52枚。引く際にカードの重複は無いようにする

・プレイヤーとディーラーの2人対戦。プレイヤーは実行者、ディーラーは自動的に実行・

・実行開始時、プレイヤーとディーラーはそれぞれ、カードを2枚引く。引いたカードは画面に表示する。ただし、ディーラーの2枚目のカードは分からないようにする

・その後、先にプレイヤーがカードを引く。プレイヤーが21を超えていたらバースト、その時点でゲーム終了

・プレイヤーは、カードを引くたびに、次のカードを引くか選択できる

・プレイヤーが引き終えたら、その後ディーラーは、自分の手札が17以上になるまで引き続ける

・プレイヤーとディーラーが引き終えたら勝負。より21に近い方の勝ち

・JとQとKは10として扱う

・Aはとりあえず「1」としてだけ扱う。「11」にはしない

・ダブルダウンなし、スプリットなし、サレンダーなし、その他特殊そうなルールなし

コード


view.rb

require './black_jack/player'

require './black_jack/card'
require './black_jack/controller'

p '今からブラックジャックを始めます'
p 'ディーラーとプレイヤーに2枚ずつカードを配ります。'

@dealer = create_player
@player = create_player

p "ディーラーの#{@dealer.hand_index(0)}"
p "あなたの#{@player.hand_index(0)}"
p "あなたの#{@player.hand_index(1)}"

2.upto(15) do |i|
p 'カードを引きますか?(y/n)'
input = gets.chomp

if input == 'y'
@player.draw
p "あなたの引いたカードは#{@player.hand[i][0]}#{@player.hand[i][1]}です"
else
break
end

if @player.card_sum > 21
p '合計が21を超えました!!!'
p 'プレイヤーの負けです!!!'
exit
end
end

p 'では、次にディーラーが引いていきたいと思います。'

while @dealer.card_sum < 17
@dealer.draw
end

p '両者引き終わりました。'
p '勝者は....'

p @player.battle(@dealer)

p 'プレイヤーのカード'
p @player.card_index

p 'ディーラーのカード'
p @dealer.card_index



login.rb

require './black_jack/player'

require './black_jack/card'

def create_player
@player = Player.new
@player.draw
@player.draw
@player
end



card.rb

class Card

MARK = ['spade', 'heart', 'diamond', 'club'].freeze
NUMBER = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
].freeze

attr_reader :mark, :number

def initialize(mark,number)
@mark = mark
@number = number
end
end



player.rb

class Player

attr_reader :hand

# 引いたカードを入れる配列
def initialize
@hand = []
end

# カードを引く処理。既に持っているカードを引いたらやり直し
def draw
@hand.uniq!
card = Card.new(Card::MARK.sample, Card::NUMBER.sample)
@hand << [card.mark, card.number]
unless @hand.count == @hand.uniq.count
draw
end
@hand
end

# 手札の内容
def hand_index(i)
"#{i + 1}枚目は#{self.hand[i][0]}#{self.hand[i][1]}です"
end

# プレイヤーのカードの合計がディーラーのカードの合計と比較する
def battle(other)
result = (card_sum - 21).abs <=> (other.card_sum - 21).abs
if result == -1
'プレイヤーです!!!'
elsif result == 0
'引き分けです!!!'
else
'ディーラーです!!!'
end
end

# カードの合計を出す。
def card_sum
sum = 0
@hand.each do |num|
if num[1] > 10
sum += 10
else
sum += num[1]
end
end
sum
end

# 手札の一覧を返す
def card_index
hand.map { |num| "#{num[0]}#{num[1]}" }.sort.join(',')
end
end


完成動画

実際にやってみると以下のような動画になります(リンクですいません)。

まとめ

今回は処理と出力で別のファイルにすることを特に意識しました。

実際に出力されるのはview.rbに、処理はその他のファイルに書きました。

ただ、create_playerメソッドの為だけにlogic.rbを作る必要はなかったかな〜と反省中です。

本当はplayerのインスタンスが作成された時点でdrawメソッドを2回実行させたかったけど、どうすればいいか分かりませんでした汗

後、view.rbに少しだけ処理が残ってしまいました。

こちらも今後リファクタリング 必須ですね。

ブラック・ジャックはこちらの記事にも書いてある通り、基本的な文法が理解出来ていれば出来るので、ぜひやってみてください!!!!