diff --git a/00_Common/dotnet/Games.Common/Randomness/IRandom.cs b/00_Common/dotnet/Games.Common/Randomness/IRandom.cs index 0ed4a587..9db4c12f 100644 --- a/00_Common/dotnet/Games.Common/Randomness/IRandom.cs +++ b/00_Common/dotnet/Games.Common/Randomness/IRandom.cs @@ -6,47 +6,17 @@ namespace Games.Common.Randomness; public interface IRandom { /// - /// Gets a random such that 0 <= n < 1. + /// Gets a random such that 0 <= n < 1. /// /// The random number. float NextFloat(); /// - /// Gets a random such that 0 <= n < exclusiveMaximum. - /// - /// The random number. - float NextFloat(float exclusiveMaximum); - - /// - /// Gets a random such that inclusiveMinimum <= n < exclusiveMaximum. - /// - /// The random number. - float NextFloat(float inclusiveMinimum, float exclusiveMaximum); - - /// - /// Gets a random such that 0 <= n < exclusiveMaximum. - /// - /// The random number. - int Next(int exclusiveMaximum); - - /// - /// Gets a random such that inclusiveMinimum <= n < exclusiveMaximum. - /// - /// The random number. - int Next(int inclusiveMinimum, int exclusiveMaximum); - - /// - /// Gets the previous random number as a . + /// Gets the returned by the previous call to . /// /// The previous random number. float PreviousFloat(); - /// - /// Gets the previous random number as an . - /// - /// The previous random number. - int Previous(); - /// /// Reseeds the random number generator. /// diff --git a/00_Common/dotnet/Games.Common/Randomness/IRandomExtensions.cs b/00_Common/dotnet/Games.Common/Randomness/IRandomExtensions.cs new file mode 100644 index 00000000..bfdd0b49 --- /dev/null +++ b/00_Common/dotnet/Games.Common/Randomness/IRandomExtensions.cs @@ -0,0 +1,91 @@ +using System; + +namespace Games.Common.Randomness; + +/// +/// Provides extension methods to providing random numbers in a given range. +/// +/// +public static class IRandomExtensions +{ + /// + /// Gets a random such that 0 <= n < exclusiveMaximum. + /// + /// The random number. + public static float NextFloat(this IRandom random, float exclusiveMaximum) => + Scale(random.NextFloat(), exclusiveMaximum); + + /// + /// Gets a random such that inclusiveMinimum <= n < exclusiveMaximum. + /// + /// The random number. + public static float NextFloat(this IRandom random, float inclusiveMinimum, float exclusiveMaximum) => + Scale(random.NextFloat(), inclusiveMinimum, exclusiveMaximum); + + /// + /// Gets a random such that 0 <= n < exclusiveMaximum. + /// + /// The random number. + public static int Next(this IRandom random, int exclusiveMaximum) => ToInt(random.NextFloat(exclusiveMaximum)); + + /// + /// Gets a random such that inclusiveMinimum <= n < exclusiveMaximum. + /// + /// The random number. + public static int Next(this IRandom random, int inclusiveMinimum, int exclusiveMaximum) => + ToInt(random.NextFloat(inclusiveMinimum, exclusiveMaximum)); + + /// + /// Gets the previous unscaled (between 0 and 1) scaled to a new range: + /// 0 <= x < . + /// + /// The random number. + public static float PreviousFloat(this IRandom random, float exclusiveMaximum) => + Scale(random.PreviousFloat(), exclusiveMaximum); + + /// + /// Gets the previous unscaled (between 0 and 1) scaled to a new range: + /// <= n < . + /// + /// The random number. + public static float PreviousFloat(this IRandom random, float inclusiveMinimum, float exclusiveMaximum) => + Scale(random.PreviousFloat(), inclusiveMinimum, exclusiveMaximum); + + /// + /// Gets the previous unscaled (between 0 and 1) scaled to an in a new + /// range: 0 <= n < . + /// + /// The random number. + public static int Previous(this IRandom random, int exclusiveMaximum) => + ToInt(random.PreviousFloat(exclusiveMaximum)); + + /// + /// Gets the previous unscaled (between 0 and 1) scaled to an in a new + /// range: <= n < . + /// The random number. + public static int Previous(this IRandom random, int inclusiveMinimum, int exclusiveMaximum) => + ToInt(random.PreviousFloat(inclusiveMinimum, exclusiveMaximum)); + + private static float Scale(float zeroToOne, float exclusiveMaximum) + { + if (exclusiveMaximum <= 0) + { + throw new ArgumentOutOfRangeException(nameof(exclusiveMaximum), "Must be greater than 0."); + } + + return Scale(zeroToOne, 0, exclusiveMaximum); + } + + private static float Scale(float zeroToOne, float inclusiveMinimum, float exclusiveMaximum) + { + if (exclusiveMaximum <= inclusiveMinimum) + { + throw new ArgumentOutOfRangeException(nameof(exclusiveMaximum), "Must be greater than inclusiveMinimum."); + } + + var range = exclusiveMaximum - inclusiveMinimum; + return zeroToOne * range + inclusiveMinimum; + } + + private static int ToInt(float value) => (int)Math.Floor(value); +} \ No newline at end of file diff --git a/00_Common/dotnet/Games.Common/Randomness/RandomNumberGenerator.cs b/00_Common/dotnet/Games.Common/Randomness/RandomNumberGenerator.cs index 2c8749cb..d46f72e7 100644 --- a/00_Common/dotnet/Games.Common/Randomness/RandomNumberGenerator.cs +++ b/00_Common/dotnet/Games.Common/Randomness/RandomNumberGenerator.cs @@ -2,6 +2,7 @@ using System; namespace Games.Common.Randomness; +/// public class RandomNumberGenerator : IRandom { private Random _random; @@ -13,38 +14,9 @@ public class RandomNumberGenerator : IRandom _random = new Random((int)(DateTime.UtcNow.Ticks / TimeSpan.TicksPerSecond)); } - public float NextFloat() => NextFloat(1); - - public float NextFloat(float exclusiveMaximum) - { - if (exclusiveMaximum <= 0) - { - throw new ArgumentOutOfRangeException(nameof(exclusiveMaximum), "Must be greater than 0."); - } - - return NextFloat(0, exclusiveMaximum); - } - - public float NextFloat(float inclusiveMinimum, float exclusiveMaximum) - { - if (exclusiveMaximum <= inclusiveMinimum) - { - throw new ArgumentOutOfRangeException(nameof(exclusiveMaximum), "Must be greater than inclusiveMinimum."); - } - - var range = exclusiveMaximum - inclusiveMinimum; - return _previous = ((float)_random.NextDouble()) * range + inclusiveMinimum; - } - - public int Next(int exclusiveMaximum) => ToInt(NextFloat(exclusiveMaximum)); - - public int Next(int inclusiveMinimum, int exclusiveMaximum) => ToInt(NextFloat(inclusiveMinimum, exclusiveMaximum)); + public float NextFloat() => _previous = (float)_random.NextDouble(); public float PreviousFloat() => _previous; - public int Previous() => ToInt(_previous); - - private static int ToInt(float value) => (int)Math.Floor(value); - public void Reseed(int seed) => _random = new Random(seed); -} \ No newline at end of file +}