多人数でジャンケンをするRubyのプログラム

Rubyにおけるクラスを利用したプログラムのサンプルとして、三人の相手とジャンケンをするゲームのプログラムを考えてみました。みんなでジャンケンをして、負けたら退場し、最後まで勝ち残ることを目指すというものです。

まず、プログラムの実行例を示します:

>ruby janken.rb
名前は: るびい

るびい の手は? [0] グー [1] チョキ [2] パー [9] 中断: 1

るびい は チョキ を出した。
太郎 は グー を出した。
次郎 は パー を出した。
花子 は グー を出した。

あいこ。もう一度。

るびい の手は? [0] グー [1] チョキ [2] パー [9] 中断: 0

るびい は グー を出した。
太郎 は グー を出した。
次郎 は チョキ を出した。
花子 は チョキ を出した。

るびい の勝ち。
太郎 の勝ち。

るびい の手は? [0] グー [1] チョキ [2] パー [9] 中断: 2

るびい は パー を出した。
太郎 は パー を出した。

あいこ。もう一度。

るびい の手は? [0] グー [1] チョキ [2] パー [9] 中断: 2

るびい は パー を出した。
太郎 は グー を出した。

るびい の勝ち。

再プレイしますか? [0] はい [9] いいえ: 9

プログラムは、以下のとおりです:

# ジャンケンする人を表すオブジェクトのクラス
class RPS  # Rock-Paper-Scissors
  # 定数
  Sgn = ["グー", "チョキ", "パー"]

  # アクセサ
  attr_accessor :name  # 名前
  attr_accessor :sign  # ジャンケンの手

  # initializeメソッド
  # newによるオブジェクト生成時に呼び出される
  def initialize(name="computer")
    @name = name
  end

  # クラスメソッド
  # ジャンケンの勝敗を判定する
  # 各人の勝敗の結果を並べた配列を返す
  def self.judge(*persons)
    flag = [0,0,0]
    # 各人の手を並べた配列を作成
    signs = persons.map{ |person|
      flag[person.sign] = 1
      person.sign
    }
    case flag
    # あいこのとき
    # 要素のない配列を返す
    # 全員が同じ手か、すべての手が出た
    when [1,0,0], [0,1,0], [0,0,1], [1,1,1]
      return []
    # 勝敗が決まっているとき
    # 勝ちの要素を1、負けの要素を0に変換
    # グーが勝ちのときの処理
    when [1,1,0]
      return signs.map{|item| 1-item}
    # チョキが勝ちのときの処理
    when [0,1,1]
      return signs.map{|item| 2-item}
    # パーが勝ちのときの処理
    when [1,0,1]
      return signs.map{|item| item/2}
    # 例外的な状況
    else
      return # nilを返す
    end
  end
end

# ============================

# 対戦者リスト
names = ["太郎", "次郎", "花子"]

# 名前の入力
# 入力された名前をnamesの先頭に挿入
# デフォルトは「あなた」
print "名前は: "
your_name = gets.chomp
unless your_name.empty?
  names.unshift(your_name)
else
  names.unshift("あなた")
end

# オブジェクトの生成
persons = names.map{ |name| RPS.new(name) }

loop{
  # あなたの手をセットする
  puts
  loop{
    print "#{persons[0].name} の手は? [0] グー [1] チョキ [2] パー [9] 中断: "
    your_sign = gets.chomp
    case your_sign
    when "0", "1", "2"
      persons[0].sign = your_sign.to_i
      break
    when "9"
      exit
    else
      redo
    end
  }
  # 各対戦者の手をセットする
  1.upto(persons.size-1){ |i|
    persons[i].sign = rand(3) # 乱数
  }
  # 各人の手を表示
  puts
  persons.each{ |person|
    puts "#{person.name} は #{RPS::Sgn[person.sign]} を出した。"
  }

  puts
  result = RPS.judge(*persons) # 可変長引数
  if !result
    puts "想定外の事態。"
    exit
  elsif result == []
    puts "あいこ。もう一度。"
    next
  else
    # 結果の表示
    persons.size.times{ |i|
      if result[i] == 1
        puts "#{persons[i].name} の勝ち。" 
      else
        persons[i] = nil # 敗者退場
      end
    }
    persons.compact!
    # あなたが負けるか、
    # あなただけが勝ち残れば終了
    if result[0] == 0 || persons.size == 1
      puts
      loop{
        print "再プレイしますか? [0] はい [9] いいえ: "
        case gets.chomp
        when "0"
          persons = names.map{ |name| RPS.new(name) }
          break
        when "9"
          exit
        else
          redo
        end
      }
    end
  end
}

【theme : プログラミング
【genre : コンピュータ

プロフィール

よしいず

Author:よしいず
MATHEMATICS.PDFというウェブサイトを運営しています。

管理の都合上、トラックバックとコメントはオフにしてあります。ブログ経験者なら分かっていただけると思いますが、スパム(アダルトやその他の宣伝)ばかりなのが現実です。

リンクは自由です。当サイトの記事に対する間違いの指摘・意見・感想などを述べた記事からのリンクは歓迎です。ただし、ブログ記事アップ直後はミスが多く、頻繁に修正します。場合によっては削除する可能性もあります。その際、何も断りもなく修正・削除しますがご了承ください。内容を参考にする場合には投稿後一週間ほど様子を見てからにしてください(笑)。

記事の間違いを指摘するときは、その具体的箇所、理由(仕様に反するなど)・根拠(参考にした文献など)、代替案(同じ結果を得るための正しいやり方)も教えてください。そうしないと、(指摘される側および第三者はその時点では無知の状態なので、)どこが間違いなのか分かりませんし、本当に間違っているのかどうかが判断・検証できません。実際、間違いだと指摘されたことが結局は正しかったというケースもありますので。

このブログのタイトル一覧

リンク
月別アーカイブ
カテゴリ
最新記事
検索フォーム
RSSリンクの表示