Big/Smallゲーム再考

id:hrkt0115311 さん原作のBig/Smallゲームのソースを昨日考えさえていただいたが、自分で1から書いたらどう書くだろう?と想ってリファクタリングしてみた。

条件は以下の通りとした。

  • 山札は53枚でジョーカーが1枚
  • 山札から2枚引いて判定するので同じカードは出てこない
  • ジョーカーは最強のカード
  • スートの種類は強さの判定には影響が無く、数字のみが意味を持つ
  • 数字の強さは、エースが最も強く、後はK,Q,J,10,9...の順に数字が大きいほど強い
  • 勝敗のメッセージは単純化する

追記:カードの強さ判定で、2つの山札からカードを引いた場合に両方にジョーカーがあり得る事を考慮してなかったので、判定ロジックを修正

追記2(2008.05.27):カード強さの判定で順番に依存する部分がスマートでなかったので少し修正

#山札処理系クラス
class Deck
  def initialize
    @card = (0...53).map {|i|i}
  end
  def draw
    #カード残りが無いならnil
    return nil if @card.empty?

    #カード抽出
    tar = rand(@card.size)
    card = Card.new(@card[tar])
    @card.delete_at(tar)
    return card;
  end
#カードクラス
  class Card
    attr_reader :card
    def initialize (no)
      @suit_name = %w!ハート クラブ クローバー スペード!
      @num_name  = %w!エース 2 3 4 5 6 7 8 9 10 J Q K!
      @card       = no
    end
  #自分がJokerならtrueを返す
    def joker?
      (@card == 52) ? true : false
    end
  #自分のカード名称を返す
    def name
      self.joker?() ? "ジョーカー" : "%sの%s" % [@suit_name[@card/13],@num_name[@card%13]]
    end
    def >(tar_card)
      if tar_card.joker?
        return false
      elsif self.joker?
        return true
      elsif (self.card % 13 ) == 0 and (tar_card.card % 13 != 0)
        return true
      elsif (self.card % 13 ) != 0 and (tar_card.card % 13 == 0)
        return false
      end
      return (self.card % 13 > tar_card.card % 13) ? true : false
    end
    def <(tar_card)
      self > tar_card ? false : true
    end
    def ==(tar_card)

      #同じ番号なら同じカード(2デッキ以上を想定)
      if self.card == tar_card.card
        return true
      #両方ともジョーカーだったら同じカード(山札にジョーカーが2枚以上になった場合を想定)
      elsif self.joker? and tar_card.joker?
        return true
      #片方だけがジョーカーならちがうカード
      elsif (true == self.joker? and false == tar_card.joker? ) 
                     or (false == self.joker? and true == tar_card.joker?)
        return false;
      end
      return (self.card % 13 == tar_card.card % 13) ? true : false
    end
  end
end

#カードを最初に引いておく
deck = Deck.new
first_card = deck.draw
second_card = deck.draw

#ゲーム開始のメッセージ表示
puts <<MESSAGE
ひとつ、運試しをしませんか?
これから2枚のカードを引きます
最初のカードが大きければあなたの負け、逆ならあなたの勝ちです。
それでははじめましょう。
MESSAGE

#メッセージ表示後の停止
sleep 2

#最初のカードを表示

if first_card.joker?
  puts "残念ジョーカーです。あなたの負けです。"
  puts "でも、ジョーカーをいきなり引当るなんて、"
  puts "逆に、ついてるかもしれませんね!"
  puts "どうぞよい一日を!!"
  exit
else
  puts "%sです。" % first_card.name
  puts "次のカードを引きます。"
  puts "このカードより大きければあなたの勝ちです。"
end

#初期表示したので停止
sleep 2

#2枚目表示
puts "%sです。" % second_card.name

#判定表示
if second_card == first_card
  puts "引き分けです。今日もよい一日を!"
elsif second_card > first_card
  puts "あなたの勝ちです。今日もよい一日を!"
else
  puts "あなたの負けです。お疲れさまでした。今日もよい一日を!"
end