数あるプログラム言語の中で、今最も勢いのある言語の一つRuby。

別の言語のプログラマ、プログラムに興味はあるけどやったことない人。
みんなで一緒にRubyを学びましょう。

公開日:2008.03.19

じゃんけんゲームを作る - 2

この記事はRubyやirbなどの環境構築が終わっていることを前提としています。 まだ環境構築ができていない方は以下の記事を参照して構築してください。

Rubyのインストール

前回のジャンケンプログラムの解説です。 今回はプログラムに対しての知識をある程度持っている方でないと理解は難しいかもしれません。

ます初期設定部分です。

01 : #初期設定
02 : hand = {1=> "グー", 2=>"チョキ", 3=>"パー"}
03 : win = 0
04 : lost = 0
05 : even = 0
06 : history = "戦績:"

2行目で入力される1、2、3の数字をそれぞれジャンケンのグー・チョキ・パーに割り当てるためにハッシュを利用しています。

それ以下の変数設定は勝敗分の履歴保持のためです。 最初なので0勝0敗0分ということですね。 それぞれの変数の対応は以下の通りです。

  • win = 勝数
  • lost = 負数
  • even = 引き分けの数
  • history = 過去の勝敗履歴(○○×○- のように履歴を保持)

次に画面表示を行います。

09 :     #画面表示
10 :     (1..3).each{|i|
11 :         print i, ": ", hand[i], "¥n"
12 :     }
13 :     print "e: 終了¥n"

ここでeachメソッドによるブロック構文を使用しています。 初期設定したhand変数から1、2、3に対応する文字列を取得して表示しています。 1から3という数値を表すために使用しているのが次の範囲を表す記法です。

1..3

これは実は以下の表記と同じ意味で、1以上3以下の数値の範囲を表すオブジェクトが作成されています。

Range.new(1, 3)

このオブジェクトに対してeachメソッドを使用することで、1から3が順に得られます。 ちなみに「1...3」という風にドットを3つ書くと1以上3未満を表します。 この場合は3を含まない1と2だけになります。

1から3のそれぞれの数値を変数iに代入して以下の行が実行されます。

11 :         print i, ": ", hand[i], "¥n"

すなわち次のように書くこともできます。

print 1, ": ", hand[1], "¥n"
print 2, ": ", hand[2], "¥n"
print 3, ": ", hand[3], "¥n"

hand[1], hand[2], hand[3]からはそれぞれ「グー」、「チョキ」、「パー」の文字列が取得できますので、あのような画面表示ができるということです。 同じような処理を3回も書くのがいやなので、繰り返し処理を使ったのですね。 今回はじゃんけんなので3種類しか表示するものがありませんが、これが100種類、200種類となると繰り返し処理を使わなければとてもじゃありませんが、いちいち書いていられません。

画面表示が終わると次はキー入力です。プレイやーがじゃんけんで出す手を番号で入力してもらいます。

15 :     #キー入力
16 :     key = nil
17 :     until ["1", "2", "3", "e"].member?(key)
18 :         print "入力してください"
19 :         key = gets.chomp
20 :     end

ここでもuntilという繰り返し構文を使っています。 untilとは与えた条件が「成立しない間」のみ繰り返される処理です。 whileの反対ですね。 条件として配列オブジェクトに対してmember?というメソッドを実行しています。 配列の中にその入力した文字列が存在するかどうか、すなわち入力した文字列が1, 2, 3, e のうちのどれかであることをチェックし、それ以外の文字が入力された場合は何度でも再入力を求めるという処理になっています。

少し注意すべきことは実際にキーボードから文字を入力してもらう処理は19行目です。 getsにより標準入力から1行入力した文字列を取得し、chompにより最後の改行を削除しています。

19 :         key = gets.chomp

繰り返しの一回目はまだ文字列が入力されていないため、keyにはnilが入ったままです。 これはuntilの条件を満たさないので、必ずループ処理の中に入り19行目が実行されることになります。 その後に22行目以降で入力文字列がeの場合は終了する処理を入れています。

28行目でto_iメソッドにより文字列を数値に変換。 後の勝敗判定の演算のために数値化して変数playerに代入しておきます。

28 :     player = key.to_i

ここまででプレイヤーが出した手は決定しました。今度はコンピュータの手を決めます。 31行目の処理です。 rand(3)というのは3未満の数値をランダムに発生させます。 0を含んで3未満ですから、+1することで1、2、3のどれかが決定されます。 そしてこれがコンピュータの出す手をあらわす数値となりますので変数computerに代入しておきます。

31 :     computer = rand(3) + 1

これでお互いの手が決定しました。 一応プレイヤーの手とコンピュータの手を表示しておきましょう。

33 :    #お互いの手を表示
34 :    print "あなたの手: ", hand[player], "\n" 
35 :    print "コンピュータの手: ", hand[computer], "\n"

そして勝敗判定です。 ここはいくつかの方法が考えられます。 以下のような9通りの場合わけを行うのもその一つです。

playerの値が1(グー)の場合

computerの値が1(グー) → 引き分け
computerの値が2(チョキ) → 勝ち
computerの値が3(パー) → 負け

playerの値が2(チョキ)の場合

computerの値が1(グー) → 負け
computerの値が2(チョキ) → 引き分け
computerの値が3(パー) → 勝ち

playerの値が3(パー)の場合

computerの値が1(グー) → 勝ち
computerの値が2(チョキ) → 負け
computerの値が3(パー) → 引き分け

でも上記の関係を眺めていると、どうも勝敗には法則性がありそうな気がします。 そこでここでは以下の計算を行います。

37 :     #勝敗、あいこを判定
38 :     result = (player - computer) % 3

「A % B」はAをBで割った余りの数値を返します。 この数値が0か1か2かであいこ、負け、勝ちとなります。 これがどうして勝敗の判定になるかわからない人は、実際にいろんな数値をいれて考えてみましょう。 ちなみに勘違いする人が多いですが、-2を3で割った余りは1です。

勝敗に応じて画面表示を行って、戦績を更新します。 「○勝△敗×分」という表示とともに、過去の勝敗履歴を○、×、-で表示するhistoryも表示しています。

そして、この処理全体をwhile節で囲うことで勝負は「e」を入力するまで繰り返されます。