C#のRandomの使い方|Randomクラスの機能と乱数配列の生成

- システム
エンジニア - C#のRandomを使うときどのようなことに注意すればいいですか。
- プロジェクト
マネージャー - Randomは比較的予測できてしまうため、暗号の生成に利用するのは注意が必要です。
C#のRandomとは?
C#のSystem.Randomは乱数を取得できるクラスです。乱数とは予測ができないバラバラの数のことで、ゲームや暗号処理に必須の機能です。Randomクラスでは主にNextメソッドを使用します。まずは以下のC#サンプルを実行してみてください。
1
2
3
|
Random r = new Random();
Console.WriteLine(r.Next(0, 10) + "は0から9までの乱数です。");
|
結果は以下のようになります。なお乱数なので実行するたびに結果は変わります。
7は0から9までの乱数です。
Randomクラスの機能
RandomクラスのNextメソッドには、2つのパラメータで発生する乱数の範囲指定をします。1つ目のパラメータは最小の数、2つ目のパラメータは最大の数+1を指定します。+1であることに注意しましょう。
Randomは他にも以下のような使い方ができます。
1
2
3
4
5
6
|
Random r = new Random();
Console.WriteLine(r.Next(-10, 0) + “は-10から-1までの乱数です。”);
Console.WriteLine(r.Next() + “は0から32bitのint最大値未満までの乱数です。”);
Console.WriteLine(r.NextDouble() + “は0.から1.0未満までの浮動小数点数の乱数です。”);
|
実行結果は以下になります。
-3は-10から-1までの乱数です。
492691439は0から32bitのint最大値未満までの乱数です。
0.40832412774130894は0.から1.0未満までの浮動小数点数の乱数です。
乱数配列の生成
C#のRandomクラスはbyte型の乱数の配列を簡単に作ることができます。以下のC#サンプルを実行してみてください。
1
2
3
4
5
6
7
8
9
|
Random r = new Random();
byte[] rndary = new byte[10];
r.NextBytes(rndary);
foreach (byte b in rndary)
{
Console.Write(b + “ “);
}
|
実行結果は以下のようになります。
146 188 168 77 255 14 82 139 150 224
セキュアな乱数を取得
ただし上の方法では乱数として脆弱性があります。Randomは比較的予測できてしまうため、暗号の生成に利用するのは危険です。そのためC#にはRNGCryptoServiceProviderという、より安全性の高い乱数生成アルゴリズムを用いたクラスがあります。
使用方法は以下のC#サンプルの通りで、使い方はRandomクラスとあまり変わりません。ただしパフォーマンスはRandomクラスよりずっと悪いので、リアルタイム性を要求されるゲームで何度も呼び出すような利用は避けた方が良いでしょう。
1
2
3
4
5
6
7
8
9
10
11
|
System.Security.Cryptography.RNGCryptoServiceProvider r =
new System.Security.Cryptography.RNGCryptoServiceProvider();
byte[] rndary = new byte[10];
r.GetBytes(rndary);
foreach (byte b in rndary)
{
Console.Write(b + “ “);
}
|
結果は以下のようになります。
146 236 248 202 125 80 2 225 140 162
.NET Core 2.0から改善されたRandomクラス
なおRandomクラスの解説記事を読むと、以下のように連続でRandomクラスを生成して利用すると同じ値になってしまうと書かれていることがあります。
1
2
3
4
5
|
for (int i = 0; i < 10; i++)
{
Console.WriteLine(new Random().Next());
}
|
しかし最新の環境でこれを実行すると、期待通りランダムな結果が得られます。これは.NET Core 2.0から対策がされて、連続で呼び出しても内部で適切なシード(乱数の種)による乱数を得られるようになったからです。
シードは特に指定しなくても良い
それまではRandomクラス内部ではシードは単純に時間のTickCount値を使っていたため、同時刻に複数の乱数を生成すると同じ結果になってしまっていました。.NET Core 2.0ではアルゴリズムが改善されてその心配がなくなったのです。
なお以下のようにRandomクラス生成時にシードを指定することも可能です。
ただし指定する場合は、シードが必ずユニーク値である配慮が必要になりますし、以下のような程度のシードであれば予測されてしまう可能性もあります。なので.NET Core 2.0以後であれば、シードは指定しない方がむしろ良いでしょう。
1
2
3
4
5
6
|
int seed = Environment.TickCount;
for (int i = 0; i < 10; i++)
{
Console.WriteLine(new Random(seed + i).Next());
}
|
数当てゲームのサンプル
では具体的にRandomクラスを使った簡単なゲームを作りましょう。以下のC#サンプルをご覧ください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
int seikai = new Random().Next(1, 11);
int count = 1;
Console.WriteLine(“1から10までの数を当てて下さい。”);
while (true)
{
String str = Console.ReadLine();
int kotae;
if (!int.TryParse(str, out kotae))
{
Console.WriteLine(“数値を入力してください。”);
continue;
}
if (kotae < 1 || kotae > 10)
{
Console.WriteLine(“1から10までを入力してください。”);
continue;
}
if (kotae==seikai)
{
Console.WriteLine(“正解です。”+count+”回目で当たりました。”);
break;
}
else if (kotae < seikai)
{
Console.WriteLine(“もっと大きいです。”);
}
else
{
Console.WriteLine(“もっと小さいです。”);
}
count++;
}
|
サンプルの解説 その1
上のC#サンプルの解説をします。まずフィールドのseikaiにRandomのNextメソッドで1から10までの乱数を代入します。そしてcountを1で初期化します。その後にwhile(true)で無限ループを開始します。
Console.ReadLine()で文字入力を受け付けます。結果は文字列なので、int.TryParseによりint型に変換します。この時文字列が数値でない場合、TryParseはfalseになるためエラーとします。
また数値でも、1から10ではない場合も同様にエラーとします。continueでwhileループの頭に戻ります。
サンプルの解説 その2
入力された数値がseikaiと同じならcountを表示してbreakで終了します。そうでない場合はseikaiと比較して、大きいか小さいかのヒントを出して、countを1加算してまたループします。実行すると以下のようになります。
1から10までの数を当てて下さい。
abc
数値を入力してください。
11
1から10までを入力してください。
5
もっと大きいです。
6
もっと大きいです。
7
正解です。3回目で当たりました。
- システム
エンジニア - C#でゲームを作るときRandomクラスを使用するときの注意点、理解しました。
- プロジェクト
マネージャー - 今回解説したことをしっかり理解して、今後活用してください。
C#のRandomで楽しいプログラムを作ろう
C#のRandomクラスの使い方について解説しましたが、いかがでしたでしょうか。ゲームが主な用途になるので、楽しんで利用することが出来ると思います。
ただし暗号生成に使う場合はセキュリティを考慮する必要があり、その乱数生成アルゴリズムもとても奥が深くなっています。興味のある人はぜひC#の乱数の機能を調べてみて下さい。
FEnet.NETナビ・.NETコラムは株式会社オープンアップシステムが運営しています。
株式会社オープンアップシステムはこんな会社です
秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
数多くのエンジニアが集まります。

-
スマホアプリから業務系システムまで
スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。
-
充実した研修制度
毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。
-
資格取得を応援
スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。
-
東証プライム上場企業グループ
オープンアップシステムは東証プライム上場「株式会社オープンアップグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
株式会社オープンアップシステムに興味を持った方へ
株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。


C#新着案件New Job
-
システム開発/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(新宿駅) -
システム開発/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(新宿駅) -
デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円神奈川県横浜市(桜木町駅) -
デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円神奈川県横浜市(桜木町駅) -
基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(西新宿駅) -
基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(西新宿駅)