【Ruby】rand/srandメソッドでランダムなデータの生成を楽しみましょう!

  • 2021年8月20日
  • 2021年10月16日
  • Ruby

Rubyに限らず、あらゆるプログラミング言語では、ランダムに数値を生成する「乱数生成機能」が用意されています。その中でも、Rubyには乱数を生成する方法がいくつか存在し、それぞれどのような違いあるのかを理解することが重要です。

今回は、Rubyで乱数を生成する機能を持つメソッドとして、rand()メソッドおよびsrand()メソッドの使い方をサンプルコードを交えて解説します。これらのメソッドを用いた応用プログラムも載せましたので、乱数生成の際のご参考にしてください。

なお、Rubyの魅力や特徴については以下の記事で詳しく解説していますので、こちらもぜひご覧くださいね。

おすすめ記事

みなさんこんにちは! 今回の記事は、 悩みを抱えた人 ・Rubyってどんなプログラミング言語なの?・Rubyを勉強すると将来役に立つかな?・Rubyのおすすめの学習方法が知りたい! というお悩みを解決する記事にな[…]

Rubyとは?その特徴や将来性、おすすめの学習方法まで網羅的にご紹介します

レバテックフリーランス … 業界最大級の案件数業界トップクラスの高単価報酬を誇る最大手のサービスです。実績豊富なコーディネーターが丁寧な対応をしてくれるため、案件の無理な提案はありません。フリーランスで生きていくためにはまず登録しておきましょう。
MidWorks … フリーランス賠償責任保障生命保険の折半など、フリーランスでありながらも正社員並みの保障を受けられるのが特徴です。また、経験豊富なキャリアコンサルタントによる手厚いサポートも受けられるため、安定したフリーランス生活を送りたい方には特におすすめのサービスです。
ポテパンフリーランス … IT業界・技術に詳しいコンサルタントが担当してくれるため、こちらの要望をきちんと理解した上で案件を紹介してくれます。また、案件情報のみならず、フリーランスのイロハについても教えてくれるため、フリーランスとして初めて活動される方には特におすすめのサービスです。

レバテックキャリア … ITエンジニアが利用したい転職エージェントNo.1にも選ばれており、年収600万円以上のハイクラス求人を5,000件以上も保有しています。エンジニアが転職を考えた時にまず初めに登録しておくべきサービスです。
Tech Stars Agent … Tech Stars Agentでは、担当エージェントが全員エンジニア出身のため、スキルやキャリアを見据えたきめ細かな転職支援が受けられます。運営元の株式会社Branding Engineerは、独立支援サービス「MidWorks」も展開しているため、独立を視野に入れたサポートも受けられます
転職ドラフト … 年収UP率93.8%/平均年収UP額126万円と圧倒的な年収UP率を誇るイベント型のエンジニア向け 転職サービスです。毎月1回開催され、厳選された優良IT/Web系企業約150社からダイレクトスカウトを受け取ることができます。年収アップを目指す方は登録必須です。


rand()メソッドの使用方法

まずは、rand()メソッドの使い方について解説します。rand()メソッドは、実行するごとにランダムで数値を返す機能を持つメソッドです。

サンプルコードを以下に示します。

# 引数なしで呼び出した場合
# → 0以上、1未満の小数値を生成
# 実行するたびに生成される値が変化する
generated_value = rand
p "引数なし:" + generated_value.to_s

# 引数に正の数(10)を指定
# → 0以上、引数の値未満の整数値を生成
generated_value = rand(10)
p "引数指定(10):" + generated_value.to_s

# 引数に負の数(-10)を指定
# → 0以上、引数の値の絶対値未満の整数値を生成
generated_value = rand(-10)
p "引数指定(-10):" + generated_value.to_s

# 引数に小数(4.8)を指定
# → 0以上、小数の整数部分の値(4)未満の整数値を生成
generated_value = rand(4.8)
p "引数指定(4.8):" + generated_value.to_s

rand()メソッドは、引数を指定することで整数の値を生成することができます。rand()メソッドの生成値は実行するたびに変化することにも注目です。

単に数値を設定するだけでは、乱数の生成範囲は最大値のみしか調整することができません。最小値と最大値ともに範囲を指定したい場合は、Rangeオブジェクトを引数に設定しましょう。

Rangeオブジェクトを引数に渡す場合のrand()メソッドの使い方を、サンプルコードを以下に示します。

# 引数にRangeオブジェクトを指定
# → Rangeオブジェクトの範囲内の整数値を生成
generated_value = rand(4..9)
p "引数指定(4~9):" + generated_value.to_s

# 引数にRangeオブジェクト(終端を含まない)を指定
# → Rangeオブジェクトの範囲内(終端を含まない)の整数値を生成
generated_value = rand(4...9)
p "引数指定(4~9):" + generated_value.to_s

# 引数にRangeオブジェクト(小数)を指定
# → Rangeオブジェクトの範囲内(小数)の実数値を生成
generated_value = rand(1.0..2.1)
p "引数指定(1.0~2.1):" + generated_value.to_s

# Rangeオブジェクトの最小値と最大値が逆転している
# → nilが返される
generated_value = rand(10..8)
p "引数指定(10~8):" + generated_value.to_s

Rangeオブジェクトを使用すれば、乱数の生成範囲について最小値と最大値の両方を調整することができます。また、小数をRangeオブジェクトに設定している場合は実数値を生成するということも覚えておきましょう。

srand()メソッドの使用方法

続いて、srand()メソッドの使い方について見ていきましょう。srand()メソッドは、乱数を生成する際に便利な要素である「種(シード値)」を指定する機能を持ちます。

乱数は、実行するたびに生成される値が変わるのが大きな特徴です。逆に言えば、rand()メソッドのみ利用しているプログラムは再現性がないことを意味します。再現性のないプログラムは、バグの原因を究明するうえでは足かせとなる恐れがあります。

「種」は、乱数を生成する前に設定することで、実行するたびに同じ乱数を生成できるのが主たる機能です。そのような機能を持つsrand()メソッドの使い方を、以下のサンプルコードに示します。

# シード値を設定しない場合は
# 実行するたびに生成値が変化する
p "シード値なし:" + rand(1.1..2.0).to_s

# シード値を設定
srand(100)

# シード値設定後は
# 実行するたびに生成値が変化しない
p "シード値あり:" + rand(1.1..2.0).to_s

シード値を設定していない場合の乱数(3行目)、設定した場合の乱数(10行目)の2つの生成値を何度も実行することで確認してみましょう。3行目の乱数は、毎度数値が変化するのに対し、10行目の乱数は数値が変わらないことが分かります。

rand()メソッドの応用

rand()メソッド、およびsrand()メソッドの使い方を理解したところで、ここでは乱数生成処理を使った応用的なプログラムを3つ紹介しましょう。

パスワードの生成処理

1つ目に紹介するのは、パスワードの生成処理です。ウェブやスマホなどのサービスを利用する際、初期パスワードとしてランダムな文字列が渡されることがあります。このようなランダムな文字列を生成するプログラムをrand()メソッドを使って実装することができます。

サンプルコードは、以下の通りです。

# ランダムで生成した文字を格納する配列
random_pass_str = []

# パスワードに使用できる文字を定義
usable_char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

# パスワードの長さを設定
PASS_LENGTH = 12

# 配列の要素数がパスワードの長さに達するまで繰り返す
while random_pass_str.length != PASS_LENGTH do
  # 使用できる文字からランダムに一文字抽出
  char = usable_char[rand(usable_char.length)]
  # 配列に追加
  random_pass_str.push(char)
end

# 抽出した文字列たちを連結させる
generated_pass = random_pass_str.join

p "パスワードを生成しました:" + generated_pass

パスワード生成処理を実装するうえでポイントとなるのは、サンプルコードの13行目の部分です。今回のサンプルプログラムでは、パスワードとして使用する文字を別途配列で定義し(usable_char)、その中から文字を選ぶことでパスワードを構成する文字列を作成します。

具体的には、配列の添字を指定することになりますが、その部分にrand()メソッドを利用することでランダムに指定できるように実装しているのがポイントです。

パスワードの長さだけ文字を選び出したら、join()メソッドを使って配列の全要素を連結することで、1つのパスワード文字列を生成できます。

数当てゲーム

2つ目に紹介するのは、数当てゲームです。数当てゲームとは、乱数生成処理によって生成された値が何なのかを、プレイヤーが数値を入力することで当てることを目的としています。

数当てゲームのルールは、以下の通りです。

プレイヤーが入力した値が
・生成値より小さいときは「もっと大きいです」と表示。ゲームは続行。
・生成値より大きいときは「もっと小さいです」と表示。ゲームは続行。
・生成値と等しい場合は「正解です」と表示しゲーム終了。プレイヤーの勝ち。
・プレイヤーが入力できる回数は10回。それまでに正解できなかったらプレイヤーの負け。

サンプルコードを、以下の示します。

# 1から100の範囲で正解の値を生成
answer_value = rand(1..100)

correct = false # 正解した場合にtrueとなる
count = 10 # プレイヤーが入力できる回数

# プレイヤーが正解する、または入力回数に達するまで
# 入力処理・判定処理を続行
while !correct && count.nonzero? do
  p "値を入力してください(残り" + count.to_s + "回)"

  # gets()メソッドで入力を受付
  # to_i()メソッドで数値に変換
  input_value = gets.to_i

  # 1~100の数値が入力されているかを判定
  if (1..100).include?(input_value)
    if input_value < answer_value
      p "もっと大きいです"
      count -= 1 # 回数を減らす
    elsif input_value > answer_value
      p "もっと小さいです"
      count -= 1 # 回数を減らす
    elsif input_value == answer_value
      p "正解です"
      correct = true
    end
  elsif input_value.zero?
    # 1~100以外のものが入力されたらやり直し
    p "1から100までの数値を入力してください"
  end
end

# 最終結果の表示
if correct
  p "プレイヤーの勝ち"
elsif count.zero?
  p "プレイヤーの負け"
end

p "ゲームを終了します"

数当てゲームの正解となる値は、Rangeオブジェクトとrand()メソッドを組み合わせて利用することで生み出しています(サンプルコード2行目)。

プレイヤーからの入力値受付はgets()メソッドを利用し、18行目から27行目で入力値と正解値の比較を行います。

Randomクラスとは?

Rubyでは、rand()メソッド以外にも乱数を生成するためのクラスである、Randomクラスが用意されています。

Randomクラスを使用した場合の乱数生成処理のサンプルコードを以下に示します。

# 乱数生成機能を持つオブジェクトを作成
rand_generator_1 = Random.new

# オブジェクト生成時にシード値を設定可能
rand_generator_2 = Random.new(24)

p "シード値(rand_generator_1):" + rand_generator_1.seed.to_s
p "シード値(rand_generator_2):" + rand_generator_2.seed.to_s

p "Randomオブジェクト(rand_generator_1)による乱数生成"
p "引数なし         ;" + rand_generator_1.rand.to_s
p "引数あり         :" + rand_generator_1.rand(10).to_s
p "引数あり(Range):" + rand_generator_1.rand(20..29).to_s

p "Randomオブジェクト(rand_generator_2)による乱数生成"
p "引数なし         ;" + rand_generator_2.rand.to_s
p "引数あり         :" + rand_generator_2.rand(10).to_s
p "引数あり(Range):" + rand_generator_2.rand(20..29).to_s

# 引数に負の数値を渡した場合
# → 例外が発生
# p rand_generator_1.rand(-10) # invalid argument - -10 (ArgumentError)

前節まで紹介したrand()メソッドとは違い、こちらは乱数生成機能をオブジェクトとして生成することができます。

Randomクラスのインスタンスメソッドとして用意されているrand()メソッドは、今まで紹介したrand()メソッドと同じく、引数に値やRangeオブジェクトを指定することで、乱数生成の範囲を調節可能です。

注意点として、負の数値を引数に渡すと例外が発生しプログラムの実行が途中で止まるので注意してください。

また、new()メソッドに引数を渡すことで、オブジェクト生成時にシード値を設定することが可能です。これにより、実行するたびに生成値が変化しない乱数生成オブジェクトを作成できます。

お仕事の途中ですが、少し一休みして、転職独立について考えてみませんか🙌?

現役エンジニアが選ぶおすすめの転職エージェント11選【成功談・失敗談もあります】

レバテックフリーランスの評判ってどう?【現役エンジニアが徹底解説します】

MidWorks(ミッドワークス)の評判ってどう?【現役エンジニアが徹底解説します】

日々の業務に追われて自分を見失わないよう、
定期的にキャリアを振り返るようにしておきましょう🤲

最後に

さて、ここまでRubyを使ってランダムなデータを生成する方法について解説してきましたがいかがでしたか?

Rubyには、rand()メソッドやsrand()メソッド、そしてRandomクラスが用意されていますので、用途別に使い分けられるようにしておきましょう。

また、今回ご紹介したパスワード生成プログラムを自作して、実際にパスワードを決める際に使用してみるのも面白いかもしれませんね。

このブログを通じて少しでも「傍(はた)を楽(らく)にする」ことができていれば嬉しく思います。

最後まで読んで頂きありがとうございました。