Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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

仕様
・初期カードは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に少しだけ処理が残ってしまいました。
こちらも今後リファクタリング 必須ですね。

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

keisuke713
初めまして!!! 閲覧していただきありがとうございます。 当方社会人一年目の会社員です。 独学で今はRubyをやっております。 ですので、学んだことをQiitaに投稿していこうと思います。
https://github.com/keisuke713/cities
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away