[C++] 重複しない乱数を生成する方法を解説
C++で重複しない乱数を生成するには、まず生成したい範囲の数値を格納したコンテナ(例: std::vector
)を用意し、std::shuffle
を使ってランダムに並べ替える方法が一般的です。
これにより、重複のない乱数列を効率的に得られます。
std::shuffle
には乱数エンジン(例: std::mt19937
)を渡す必要があります。
std::shuffleを使った重複しない乱数の生成
C++の標準ライブラリには、重複しない乱数を生成するための便利な関数std::shuffle
があります。
この関数を使用することで、指定した範囲の要素をランダムに並べ替えることができます。
以下に、std::shuffle
を使った重複しない乱数の生成方法を示します。
#include <iostream>
#include <vector>
#include <algorithm> // std::shuffle
#include <random> // std::default_random_engine
#include <ctime> // std::time
int main() {
// 1から10までの整数を格納するベクター
std::vector<int> numbers;
for (int i = 1; i <= 10; ++i) {
numbers.push_back(i); // ベクターに整数を追加
}
// 乱数生成器の初期化
std::default_random_engine engine(static_cast<unsigned int>(std::time(nullptr)));
// ベクターの要素をシャッフル
std::shuffle(numbers.begin(), numbers.end(), engine);
// シャッフルされた結果を出力
std::cout << "重複しない乱数: ";
for (const auto& number : numbers) {
std::cout << number << " "; // 各要素を出力
}
std::cout << std::endl; // 改行
return 0;
}
重複しない乱数: 3 7 1 5 9 2 10 6 4 8
このコードでは、1から10までの整数を含むベクターを作成し、std::shuffle
を使ってその要素をランダムに並べ替えています。
乱数生成器にはstd::default_random_engine
を使用し、シード値として現在の時刻を指定しています。
これにより、毎回異なる乱数の並びが得られます。
std::setを使った重複しない乱数の生成
C++のstd::set
は、重複しない要素を自動的に管理するデータ構造です。
この特性を利用して、重複しない乱数を生成することができます。
以下に、std::set
を使った重複しない乱数の生成方法を示します。
#include <iostream>
#include <set> // std::set
#include <random> // std::default_random_engine
#include <ctime> // std::time
int main() {
// 重複しない乱数を格納するセット
std::set<int> uniqueNumbers;
// 乱数生成器の初期化
std::default_random_engine engine(static_cast<unsigned int>(std::time(nullptr)));
std::uniform_int_distribution<int> distribution(1, 10); // 1から10までの乱数
// 5つの重複しない乱数を生成
while (uniqueNumbers.size() < 5) {
int randomNumber = distribution(engine); // 乱数を生成
uniqueNumbers.insert(randomNumber); // セットに追加
}
// 生成された重複しない乱数を出力
std::cout << "重複しない乱数: ";
for (const auto& number : uniqueNumbers) {
std::cout << number << " "; // 各要素を出力
}
std::cout << std::endl; // 改行
return 0;
}
重複しない乱数: 2 5 7 9 10
このコードでは、std::set
を使用して重複しない乱数を生成しています。
std::uniform_int_distribution
を使って1から10までの乱数を生成し、std::set
に追加することで、重複を自動的に排除しています。
最終的に、5つの重複しない乱数が生成され、出力されます。
特定の範囲で重複しない乱数を生成する方法
特定の範囲内で重複しない乱数を生成するには、std::vector
とstd::shuffle
を組み合わせる方法が一般的です。
この方法では、まず指定した範囲の整数をベクターに格納し、その後std::shuffle
を使ってランダムに並べ替えます。
以下に、特定の範囲で重複しない乱数を生成する方法を示します。
#include <iostream>
#include <vector>
#include <algorithm> // std::shuffle
#include <random> // std::default_random_engine
#include <ctime> // std::time
int main() {
// 1から20までの整数を格納するベクター
std::vector<int> numbers;
for (int i = 1; i <= 20; ++i) {
numbers.push_back(i); // ベクターに整数を追加
}
// 乱数生成器の初期化
std::default_random_engine engine(static_cast<unsigned int>(std::time(nullptr)));
// ベクターの要素をシャッフル
std::shuffle(numbers.begin(), numbers.end(), engine);
// 生成された重複しない乱数を出力(最初の5つを表示)
std::cout << "重複しない乱数 (1から20の範囲): ";
for (int i = 0; i < 5; ++i) {
std::cout << numbers[i] << " "; // 最初の5つの要素を出力
}
std::cout << std::endl; // 改行
return 0;
}
重複しない乱数 (1から20の範囲): 14 3 19 7 1
このコードでは、1から20までの整数を含むベクターを作成し、std::shuffle
を使ってその要素をランダムに並べ替えています。
出力では、生成された重複しない乱数の中から最初の5つを表示しています。
この方法を使うことで、特定の範囲内で重複しない乱数を簡単に生成することができます。
大量の重複しない乱数を効率的に生成する方法
大量の重複しない乱数を効率的に生成するためには、std::vector
を使用して必要な範囲の整数を格納し、std::shuffle
でシャッフルする方法が効果的です。
この方法は、特に大きな範囲の整数を扱う場合に便利です。
以下に、大量の重複しない乱数を生成する方法を示します。
#include <iostream>
#include <vector>
#include <algorithm> // std::shuffle
#include <random> // std::default_random_engine
#include <ctime> // std::time
int main() {
const int totalNumbers = 1000; // 生成する乱数の総数
std::vector<int> numbers(totalNumbers); // ベクターを初期化
// 1から1000までの整数をベクターに格納
for (int i = 0; i < totalNumbers; ++i) {
numbers[i] = i + 1; // ベクターに整数を追加
}
// 乱数生成器の初期化
std::default_random_engine engine(static_cast<unsigned int>(std::time(nullptr)));
// ベクターの要素をシャッフル
std::shuffle(numbers.begin(), numbers.end(), engine);
// 生成された重複しない乱数を出力(最初の10個を表示)
std::cout << "重複しない乱数 (1から1000の範囲): ";
for (int i = 0; i < 10; ++i) {
std::cout << numbers[i] << " "; // 最初の10個の要素を出力
}
std::cout << std::endl; // 改行
return 0;
}
重複しない乱数 (1から1000の範囲): 456 789 12 345 678 1 234 567 890 100
このコードでは、1から1000までの整数を含むベクターを作成し、std::shuffle
を使ってその要素をランダムに並べ替えています。
出力では、生成された重複しない乱数の中から最初の10個を表示しています。
この方法を使用することで、大量の重複しない乱数を効率的に生成することが可能です。
実用的な応用例
重複しない乱数の生成は、さまざまなアプリケーションで利用されます。
以下に、C++での実用的な応用例をいくつか紹介します。
1. ゲームのランダムイベント
ゲームでは、プレイヤーに対してランダムなアイテムや敵を生成することがよくあります。
重複しない乱数を使用することで、同じアイテムや敵が重複して出現することを防ぎ、ゲームのバランスを保つことができます。
#include <iostream>
#include <vector>
#include <algorithm> // std::shuffle
#include <random> // std::default_random_engine
#include <ctime> // std::time
int main() {
// ゲームアイテムのリスト
std::vector<std::string> items = {"剣", "盾", "ポーション", "弓", "魔法の杖"};
std::default_random_engine engine(static_cast<unsigned int>(std::time(nullptr)));
// アイテムをシャッフル
std::shuffle(items.begin(), items.end(), engine);
// プレイヤーに配布するアイテムを表示
std::cout << "プレイヤーに配布するアイテム: ";
for (int i = 0; i < 3; ++i) {
std::cout << items[i] << " "; // 最初の3つのアイテムを出力
}
std::cout << std::endl; // 改行
return 0;
}
プレイヤーに配布するアイテム: 魔法の杖 ポーション 剣
2. 抽選やクジ引き
抽選やクジ引きのシステムでは、参加者の中からランダムに選ばれる必要があります。
重複しない乱数を使用することで、同じ参加者が複数回選ばれることを防ぎます。
#include <iostream>
#include <vector>
#include <algorithm> // std::shuffle
#include <random> // std::default_random_engine
#include <ctime> // std::time
int main() {
// 参加者のリスト
std::vector<std::string> participants = {"田中", "鈴木", "佐藤", "高橋", "山田"};
std::default_random_engine engine(static_cast<unsigned int>(std::time(nullptr)));
// 参加者をシャッフル
std::shuffle(participants.begin(), participants.end(), engine);
// 抽選結果を表示
std::cout << "抽選結果: " << participants[0] << "さんが当選しました!" << std::endl; // 最初の1人を出力
return 0;
}
抽選結果: 鈴木さんが当選しました!
3. データサンプリング
データ分析や機械学習の分野では、大量のデータからランダムにサンプルを抽出することが必要です。
重複しない乱数を使用することで、同じデータが複数回選ばれることを防ぎ、正確な分析が可能になります。
これらの応用例からもわかるように、重複しない乱数の生成は、さまざまな分野で重要な役割を果たしています。
C++を使用することで、簡単に実装することができ、効率的なプログラムを作成することが可能です。
まとめ
この記事では、C++を使用して重複しない乱数を生成するさまざまな方法について解説しました。
std::shuffle
やstd::set
を利用することで、特定の範囲や大量の乱数を効率的に生成することが可能であり、ゲームや抽選、データサンプリングなどの実用的な応用例も紹介しました。
これらの技術を活用して、プログラムの中でランダム性を取り入れ、より魅力的で機能的なアプリケーションを作成してみてください。