概要
rubyでドローポーカーを作ってみる~準備編~
↓
rubyでドローポーカーを作ってみる~test-unit準備編~
↓
rubyでドローポーカーを作ってみる~実装編1(カード)~
↓
rubyでドローポーカーを作ってみる~実装編2(役)~
↓
rubyでドローポーカーを作ってみる~実装編3(プレイヤー)~
に続いて。
ソース: https://github.com/rytkmt/ruby_poker
山札の実装
はい、では今回も同じくまずは要件の整理からいきます。
- はじめは13 x 4のカードを全て使用して山札を作成する
- カードの並び順はばらばら
- 手札交換を行って不要になったカードは回収する
- 山札から任意の枚数をドローする
- ドローする枚数が足りなくなった場合、手札交換にて不要になったカードをまぜてシャッフルしてそこから引く
という感じですかね。
プレイヤーの手札交換の修正
ここで気づいてしまいましたが、前回のプレイヤーの実装にて手札交換でただ手札のカードから削除するだけと実装してしまっていたため
捨てるカードを回収するように修正します・・
def change(indexes:, new_cards:)
raise(ArgumentError) unless indexes.size == new_cards.size
raise(ArgumentError) unless indexes.all? { |i| (0..4).include?(i) }
- indexes.sort.reverse_each { |i| @cards.delete_at(i) }
+ trushed = indexes.sort.reverse.each_with_object([]) { |i, trushed| trushed << @cards.delete_at(i) }
@cards += new_cards
@hand = Hand.new(cards: @cards)
+ trushed
end
山札の作成
module RubyPoker
class Deck
def initialize
@cards = init_cards
@trushed = []
end
private
def init_cards
RubyPoker::SUITS.each_with_object([]) do |suit, cards|
cards.concat(
RubyPoker::NUMBERS.map { |number| Card.new(suit: suit, number: number) }
)
end.shuffle
end
end
end
始め、each_with_object内で+=
を使って実装したのですが、よくよく考えるとこれは+
で結合したものを=
で変数代入してるので同一の変数に結合した別オブジェクトを格納しているだけで、破壊的な変更を行っているわけではないのでうまくいかなかったです。
破壊的にcardsを変更するためにconcat
を使います。
手札交換によるカードの回収
プレイヤーの#change
にて返ってきた不要カードを回収して保持しておくだけなので簡単です
def trush(cards:)
@trushed += cards
end
カードのドロー
- 山札から任意の枚数をドローする
- ドローする枚数が足りなくなった場合、手札交換にて不要になったカードをまぜてシャッフルしてそこから引く
def draw(count:)
merge_trushed if @cards.size < count
raise(ArgumentError, "No cards.") if @cards.size < count
@cards.shift(count)
end
private
def merge_trushed
@cards += @trushed
@cards.shuffle!
@trushed = []
end
足りなくなるってプレイ人数の設定がイケてないだけな気がするので、そこは起こらない前提でエラーを吐くようにしました。
終わりに
山札もシンプルでしたね。
これで次こそゲーム進行回りの実装に入れるかな?と思います。
完成も近づいてきました。4連休で終わらせてしまいたいですし最後までやってしまいます。