Random.Range()
を使用して値を生成している場合、範囲内の一部の値を除外する方法はありますか(たとえば、6から8ではなく1から20までの数値を選択してください)。
これを行う最良の方法は、お気に入りのジェネレーターを使用して1〜17の整数n
を生成し、を使用して変換することです。
if (n > 5){
n += 3;
}
1から20の間でサンプリングしてから値を破棄すると、統計的な異常が発生する可能性があります。 (たとえば、乱数ジェネレーターが線形合同法である場合、分散が高すぎます。試してみてください。)
だからあなたは実際に17
(20-3)異なる値
[1..5] U [9..20]
そして、あなたはこのようなものを実装することができます:
// Simplest, not thread-safe
private static Random random = new Random();
...
int r = (r = random.Next(1, 17)) > 5
? r + 3
: r;
一般的な(そして複雑な)ケースでは、すべての可能な値の配列を生成し、そこからアイテムを取得することをお勧めします。
int[] values = Enumerable
.Range(1, 100) // [1..100], but
.Where(item => item % 2 == 1) // Odd values only
.Where(item => !(item >= 5 && item <= 15)) // with [5..15] range excluded
//TODO: Add as many conditions via .Where(item => ...) as you want
.ToArray();
...
int r = values[random.Next(values.Length)];
はい、LINQでwhere
ステートメントを使用するだけです。
var list = Enumerable.Range(1, 20).Where(a => a < 6 || a > 8).ToArray();
LINQを使用しない他の方法
public IEnumerable RangeBetween()
{
foreach (var i in Enumerable.Range(1, 20))
{
if (i < 6 || i > 8)
{
yield return i;
}
}
}
編集:今、私は厳密なC#の質問ではないことがわかりました。 Unity
とRandom
に影響します。しかし、完全な答えを得るには、上記のコードをEnumerable.Range
とともに使用し、次にこれを使用して番号を生成すると思います。
list[Random.Next(list.Length)];
もう1つの方法は、有効な戻り値の配列を作成してから、ランダムに1つを選択することです。
void Main()
{
var rng = new Random();
var validValues = Enumerable.Range(1, 20).Except(new int[] {6, 7, 8}).ToArray();
for (int i = 0; i < 25; i++)
{
Console.Write(validValues[rng.Next(0, validValues.Length)]);
Console.Write(" ");
}
}
編集:おっと!これはUnity3D用であるため、この例は適切でない可能性があることに気づきました。ただし、標準のRandom
クラスを使用して機能します。
Rが6〜8の範囲にある場合、これは別の乱数を選択します。
int r = 0;
do
{
r = Random.Next(20);
} while (r >= 6 && r <= 8)