Rubyの基礎文法を勉強したときに知識を定着させるために作成したブラックジャックゲームです。
ちなみに、プログラミングを勉強して初めて作った成果物。
実行動画
実装部分
実装の前にマインドマップを作って各クラスの各メソッドが何をするのかを明確にしてから作りました。
Blackjackクラス
require "./deck.rb"
require "./card.rb"
require "./user.rb"
require "./dealer.rb"
require "./message.rb"
#ゲーム進行
class Blackjack
include Message
def game_start
start_msg
deck = Deck.new
user = User.new
dealer = Dealer.new
#手札配る、手札表示
user.user_first_draw_card(deck)
dealer.dealer_first_draw(deck)
#ユーザーターン
#Hitならもう一枚引く、スタンドならループ抜ける
while true
select_msg
#行動選択
select_num = gets.to_i
if select_num == 1
user.draw(deck)
user.show_hand
if user.cal_score_user >= 22
burst_msg
return
end
elsif select_num == 2
break
else
error_msg
end
end
#ディーラーターン
#17以上になるまで引く
while true
if dealer.cal_score_dealer <= 17
dealer.draw(deck)
else
break
end
end
user.show_hand
dealer.show_hand
judge(user, dealer)
end
def judge(user, dealer)
user_score = user.cal_score_user
dealer_score = dealer.cal_score_dealer
if user_score == dealer_score
draw_msg
elsif user_score == 21
blackjack_msg
elsif dealer_score >= 22
dealer_burst_msg
elsif dealer_score > user_score
user_lose_msg
else
user_win_msg
end
end
end
ゲームコントローラー部分。
Userはカードを引くか引かないかの行動を選べて、Dealerは18以上になるまでカードを引き続ける処理を書いてます。
プレイヤーが21以上の点数になったら即バーストで負け、21ちょうどならブラックジャックの表記が出て勝ち。
メッセージ部分はmessage.rb
に切り出してます。
Deckクラス
#山札作成、シャフル、ドロー
class Deck
#山札用の空の配列を用意
def initialize
@cards = []
end
#山札作成、シャッフル
def create
mark = ["ハート","クローバー","ダイヤ","スペード"]
number = ["A","2","3","4","5","6","7","8","9","10","J","Q","K"]
mark.each do |mark|
number.each do |number|
card = Card.new(mark,number)
@cards << card
end
end
@cards.shuffle!
end
#山札から1枚引く
def draw
@cards.pop
end
end
ここではカードデッキの生成とカードを引く処理の部分です。
カードをデッキから引く処理は配列の末尾要素を削除するpop
メソッドを使うことで実現しています。
Cardクラス
#カード情報
class Card
attr_reader :mark,:number
#カードオブジェクトの値受け取り
def initialize(mark,number)
@mark = mark
@number = number
end
#カード情報表示
def info
return "#{@mark}の#{@number}"
end
#スコア計算方法
def score
if @number == "J" || @number == "Q" || @number == "K"
@nunmber = 10
elsif @number == "A"
@number = 1
else
@number.to_i
end
end
end
スコア計算の部分は、JQKを10点Aは1点として扱っています。
本当のBJだとAは1点か11点のどちらか都合の良い方で扱えるけど難しくて実装断念した‥
Done is better than perfect ってことで今回はとりあえずこれで、今後時間があれば実装します 笑
Userクラス
class User
def initialize
@user_hands = []
end
#最初に引く、手札公開
def user_first_draw_card(deck)
2.times do
deck.create
card = deck.draw
@user_hands << card
end
puts "====あなたの手札======="
@user_hands.each.with_index(1) do |user_hand, i|
puts "#{i}枚目 : #{user_hand.info}"
end
puts "あなたの合計点数は#{cal_score_user}です"
puts "========================"
end
def cal_score_user
user_score = 0
@user_hands.each do |hand|
user_score += hand.score
end
return user_score #合計のスコアスコアを返す
end
#1枚引く
def draw(deck)
deck.create
card = deck.draw
@user_hands << card
end
#手札表示
def show_hand
puts ""
puts "====あなたの手札======="
@user_hands.each.with_index(1) do |user_hand, i|
puts "#{i}枚目 : #{user_hand.info}"
end
puts "あなたの合計点数は#{cal_score_user}です"
puts "========================"
puts ""
end
end
Userは最初に2枚手札を配られて、Hitを選択したときに1枚ずつデッキからカードを引くっていう処理。
Dealerクラス
class Dealer
def initialize
@dealer_hands = []
end
#最初に引く、手札公開
def dealer_first_draw(deck)
2.times do
deck.create
card = deck.draw
@dealer_hands << card
end
puts <<~TEXT
====ディーラーの手札====
1枚目:#{@dealer_hands.first.info}
2枚目:伏せられている
========================
TEXT
end
#ディーラーのスコア計算
def cal_score_dealer
dealer_score = 0
@dealer_hands.each do |hand|
dealer_score += hand.score
end
return dealer_score #2枚の合計のスコア
end
def draw(deck)
deck.create
card = deck.draw
@dealer_hands << card
end
def show_hand
puts ""
puts "====ディーラーの手札===="
@dealer_hands.each.with_index(1) do |dealer_hand, i|
puts "#{i}枚目 : #{dealer_hand.info}"
end
puts "あなたの合計点数は#{cal_score_dealer}です"
puts "========================"
puts ""
end
end
やっていることはUserと大体同じだけどDealerの場合は2枚配られてカードを1枚伏せてる状態にしてる。
Messageモジュール
module Message
def start_msg
puts <<~TEXT
=======================
Welcome to Blackjack!!!
=======================
TEXT
end
def select_msg
puts <<~TEXT
どうしますか?
1.Hit(カードを引く)
2.Stand(今の手札で勝負)
TEXT
end
def burst_msg
puts "バースト!!"
puts "合計点数が21を超えたのであなたの負けです。"
end
def error_msg
puts "1 or 2 を入力してください。"
end
def draw_msg
puts "同点なので引き分けです。"
end
def blackjack_msg
puts "ブラックジャック!! あなたの勝ちです!"
end
def dealer_burst_msg
puts "ディーラーがバーストしました。あなたの勝ちです!"
end
def user_lose_msg
puts "ディーラーの勝ちです!"
end
def user_win_msg
puts "あなたの勝ちです!"
end
end
Blackjacクラスの出力メッセージはメッセージモジュールとして切り出して処理のみにすることで可読性を上げています。
Main
require "./blackjack.rb"
blackjack = Blackjack.new
blackjack.game_start
最後に 実行するmain部分。
ここでblackjack.game_start
を呼び出すことでゲームが始まる。
# 感想
実際にコードに落とし込む作業は基礎文法を勉強しているときとは比べ物にならないくらい大変でした。
それでも作っているときの楽しさ、実際に完成して動いた時の感動は忘れられません。
次はAの処理や掛け金機能を追加して、よりゲーム性を高めていきたいと思います。