#if FANTASY_WEBGL using System; using System.Collections.Generic; using System.Linq; using System.Numerics; namespace Fantasy.Helper { /// /// 随机数操作助手类,提供各种随机数生成和操作方法。 /// public static partial class RandomHelper { private static readonly Random Random = new Random(); private static readonly byte[] Byte8 = new byte[8]; private static readonly byte[] Byte2 = new byte[2]; /// /// 生成一个随机的无符号 64 位整数。 /// /// 无符号 64 位整数。 public static ulong RandUInt64() { Random.NextBytes(Byte8); return BitConverter.ToUInt64(Byte8, 0); } /// /// 生成一个随机的 64 位整数。 /// /// 64 位整数。 public static long RandInt64() { Random.NextBytes(Byte8); return BitConverter.ToInt64(Byte8, 0); } /// /// 生成一个随机的无符号 32 位整数。 /// /// 无符号 32 位整数。 public static uint RandUInt32() { return (uint) Random.Next(); } /// /// 生成一个随机的无符号 16 位整数。 /// /// 无符号 16 位整数。 public static ushort RandUInt16() { Random.NextBytes(Byte2); return BitConverter.ToUInt16(Byte2, 0); } /// /// 在指定范围内生成一个随机整数(包含下限,不包含上限)。 /// /// 下限。 /// 上限。 /// 生成的随机整数。 public static int RandomNumber(int lower, int upper) { return Random.Next(lower, upper); } /// /// 生成一个随机的布尔值。 /// /// 随机的布尔值。 public static bool RandomBool() { return Random.Next(2) == 0; } /// /// 从数组中随机选择一个元素。 /// /// 数组元素的类型。 /// 要选择的数组。 /// 随机选择的数组元素。 public static T RandomArray(this T[] array) { return array[RandomNumber(0, array.Count())]; } /// /// 从列表中随机选择一个元素。 /// /// 列表元素的类型。 /// 要选择的列表。 /// 随机选择的列表元素。 public static T RandomArray(this List array) { return array[RandomNumber(0, array.Count())]; } /// /// 打乱列表中元素的顺序。 /// /// 列表元素的类型。 /// 要打乱顺序的列表。 public static void BreakRank(List arr) { if (arr == null || arr.Count < 2) { return; } for (var i = 0; i < arr.Count / 2; i++) { var index = Random.Next(0, arr.Count); (arr[index], arr[arr.Count - index - 1]) = (arr[arr.Count - index - 1], arr[index]); } } /// /// 生成一个介于 0 和 1 之间的随机单精度浮点数。 /// /// 随机单精度浮点数。 public static float RandFloat01() { var value = Random.NextDouble(); return (float) value; } private static int Rand(int n) { var rd = new Random(); // 注意,返回值是左闭右开,所以maxValue要加1 return rd.Next(1, n + 1); } /// /// 根据权重随机选择一个索引。 /// /// 权重数组,每个元素表示相应索引的权重。 /// 随机选择的索引值。 public static int RandomByWeight(int[] weights) { var sum = weights.Sum(); var numberRand = Rand(sum); var sumTemp = 0; for (var i = 0; i < weights.Length; i++) { sumTemp += weights[i]; if (numberRand <= sumTemp) { return i; } } return -1; } /// /// 根据固定概率随机选择一个索引,即某个数值上限内随机多少次。 /// /// 概率数组,每个元素表示相应索引的概率。 /// 随机选择的索引值。 public static int RandomByFixedProbability(int[] args) { var argCount = args.Length; var sum = args.Sum(); var random = Random.NextDouble() * sum; while (sum > random) { sum -= args[argCount - 1]; argCount--; } return argCount; } /// /// 返回随机数。 /// /// 是否包含负数。 /// 返回一个随机的单精度浮点数。 public static float NextFloat(bool containNegative = false) { float f; var buffer = new byte[4]; if (containNegative) { do { Random.NextBytes(buffer); f = BitConverter.ToSingle(buffer, 0); } while ((f >= float.MinValue && f < float.MaxValue) == false); return f; } do { Random.NextBytes(buffer); f = BitConverter.ToSingle(buffer, 0); } while ((f >= 0 && f < float.MaxValue) == false); return f; } /// /// 返回一个小于所指定最大值的非负随机数。 /// /// 要生成的随机数的上限(随机数不能取该上限值)。 maxValue 必须大于或等于零。 /// 大于等于零且小于 maxValue 的单精度浮点数,即:返回值的范围通常包括零但不包括 maxValue。 不过,如果 maxValue 等于零,则返回 maxValue。 public static float NextFloat(float maxValue) { if (maxValue.Equals(0)) { return maxValue; } if (maxValue < 0) { throw new ArgumentOutOfRangeException("“maxValue”必须大于 0。", "maxValue"); } float f; var buffer = new byte[4]; do { Random.NextBytes(buffer); f = BitConverter.ToSingle(buffer, 0); } while ((f >= 0 && f < maxValue) == false); return f; } /// /// 返回一个指定范围内的随机数。 /// /// 返回的随机数的下界(随机数可取该下界值)。 /// 返回的随机数的上界(随机数不能取该上界值)。 maxValue 必须大于或等于 minValue。 /// 一个大于等于 minValue 且小于 maxValue 的单精度浮点数,即:返回的值范围包括 minValue 但不包括 maxValue。 如果 minValue 等于 maxValue,则返回 minValue。 public static float NextFloat(float minValue, float maxValue) { if (minValue.Equals(maxValue)) { return minValue; } if (minValue > maxValue) { throw new ArgumentOutOfRangeException("“minValue”不能大于 maxValue。", "minValue"); } float f; var buffer = new byte[4]; do { Random.NextBytes(buffer); f = BitConverter.ToSingle(buffer, 0); } while ((f >= minValue && f < maxValue) == false); return f; } /// /// 在指定的矩形区域内随机生成一个二维向量位置。 /// /// X轴最小值。 /// X轴最大值。 /// Y轴最小值。 /// Y轴最大值。 /// 随机生成的二维向量位置。 public static Vector2 NextVector2(float minX, float maxX, float minY, float maxY) { return new Vector2(NextFloat(minX, maxX), NextFloat(minY, maxY)); } /// /// 生成指定长度的随机数字代码。 /// /// 数字代码的长度。 /// 生成的随机数字代码。 public static string RandomNumberCode(int len = 6) { int num = 0; for (int i = 0; i < len; i++) { int number = RandomNumber(0, 10); num = num * 10 + number; } return num.ToString(); } } } #endif