Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / common / SeedRandom.cs
  1.  
  2. using System;
  3. using System.Collections.Generic;
  4. using Godot;
  5.  
  6. /// <summary>
  7. /// 随机数类
  8. /// </summary>
  9. public class SeedRandom
  10. {
  11. /// <summary>
  12. /// 种子值
  13. /// </summary>
  14. public int Seed { get; }
  15. private Random _random;
  16. private static int _staticSeed = 0;
  17. public SeedRandom(int seed)
  18. {
  19. Seed = seed;
  20. _random = new Random(seed);
  21. }
  22.  
  23. public SeedRandom()
  24. {
  25. var dateTime = DateTime.Now;
  26. var num = dateTime.Year * 100000 + dateTime.Month * 100000 + dateTime.Day * 100000 + dateTime.Hour * 10000 + dateTime.Minute * 100 + dateTime.Second;
  27. num += _staticSeed;
  28. _staticSeed += 11111;
  29. Seed = num;
  30. _random = new Random(num);
  31. }
  32. /// <summary>
  33. /// 返回一个随机的double值
  34. /// </summary>
  35. public double RandomDouble()
  36. {
  37. return _random.NextDouble();
  38. }
  39. /// <summary>
  40. /// 返回随机 boolean 值
  41. /// </summary>
  42. public bool RandomBoolean()
  43. {
  44. return _random.NextSingle() >= 0.5f;
  45. }
  46. /// <summary>
  47. /// 指定概率会返回 true, probability 范围 0 - 1
  48. /// </summary>
  49. public bool RandomBoolean(float probability)
  50. {
  51. return _random.NextSingle() <= probability;
  52. }
  53.  
  54. /// <summary>
  55. /// 返回一个区间内的随机小数
  56. /// </summary>
  57. public float RandomRangeFloat(float min, float max)
  58. {
  59. if (min == max) return min;
  60. if (min > max)
  61. return _random.NextSingle() * (min - max) + max;
  62. return _random.NextSingle() * (max - min) + min;
  63. }
  64.  
  65. /// <summary>
  66. /// 返回一个区间内的随机整数
  67. /// </summary>
  68. public int RandomRangeInt(int min, int max)
  69. {
  70. if (min == max) return min;
  71. if (min > max)
  72. return Mathf.FloorToInt(_random.NextSingle() * (min - max + 1) + max);
  73. return Mathf.FloorToInt(_random.NextSingle() * (max - min + 1) + min);
  74. }
  75.  
  76. /// <summary>
  77. /// 根据配置表中配置的范围数据, 随机返回范围内的一个值
  78. /// </summary>
  79. public int RandomConfigRange(int[] range)
  80. {
  81. return RandomRangeInt(Utils.GetConfigRangeStart(range), Utils.GetConfigRangeEnd(range));
  82. }
  83.  
  84. /// <summary>
  85. /// 根据配置表中配置的范围数据, 随机返回范围内的一个值
  86. /// </summary>
  87. public float RandomConfigRange(float[] range)
  88. {
  89. return RandomRangeFloat(Utils.GetConfigRangeStart(range), Utils.GetConfigRangeEnd(range));
  90. }
  91.  
  92. /// <summary>
  93. /// 随机返回其中一个参数
  94. /// </summary>
  95. public T RandomChoose<T>(params T[] list)
  96. {
  97. if (list.Length == 0)
  98. {
  99. return default;
  100. }
  101.  
  102. return list[RandomRangeInt(0, list.Length - 1)];
  103. }
  104.  
  105. /// <summary>
  106. /// 随机返回集合中的一个元素
  107. /// </summary>
  108. public T RandomChoose<T>(List<T> list)
  109. {
  110. if (list.Count == 0)
  111. {
  112. return default;
  113. }
  114.  
  115. return list[RandomRangeInt(0, list.Count - 1)];
  116. }
  117.  
  118. /// <summary>
  119. /// 随机返回集合中的一个元素, 并将其从集合中移除
  120. /// </summary>
  121. public T RandomChooseAndRemove<T>(List<T> list)
  122. {
  123. if (list.Count == 0)
  124. {
  125. return default;
  126. }
  127.  
  128. var index = RandomRangeInt(0, list.Count - 1);
  129. var result = list[index];
  130. list.RemoveAt(index);
  131. return result;
  132. }
  133.  
  134. /// <summary>
  135. /// 从权重列表中随机抽取下标值
  136. /// </summary>
  137. public int RandomWeight(List<int> weightList)
  138. {
  139. // 计算总权重
  140. var totalWeight = 0;
  141. foreach (var weight in weightList)
  142. {
  143. totalWeight += weight;
  144. }
  145. var randomNumber = _random.Next(totalWeight);
  146. var currentWeight = 0;
  147. for (var i = 0; i < weightList.Count; i++)
  148. {
  149. var value = weightList[i];
  150. currentWeight += value;
  151. if (randomNumber < currentWeight)
  152. {
  153. return i;
  154. }
  155. }
  156.  
  157. return RandomRangeInt(0, weightList.Count - 1);
  158. }
  159. /// <summary>
  160. /// 从权重列表中随机抽取下标值
  161. /// </summary>
  162. public int RandomWeight(int[] weightList)
  163. {
  164. // 计算总权重
  165. var totalWeight = 0;
  166. foreach (var weight in weightList)
  167. {
  168. totalWeight += weight;
  169. }
  170. var randomNumber = _random.Next(totalWeight);
  171. var currentWeight = 0;
  172. for (var i = 0; i < weightList.Length; i++)
  173. {
  174. var value = weightList[i];
  175. currentWeight += value;
  176. if (randomNumber < currentWeight)
  177. {
  178. return i;
  179. }
  180. }
  181.  
  182. return RandomRangeInt(0, weightList.Length - 1);
  183. }
  184. /// <summary>
  185. /// 返回指定区域内的随机坐标点, 该函数比较慢, 请谨慎调用
  186. /// </summary>
  187. public Vector2[] GetRandomPositionInPolygon(List<Vector2> vertices, List<int[]> polygons, int count)
  188. {
  189. if (vertices.Count == 0 || polygons.Count == 0)
  190. {
  191. return Vector2.Zero.MakeArray(count);
  192. }
  193. var minX = int.MaxValue;
  194. var maxX = int.MinValue;
  195. var minY = int.MaxValue;
  196. var maxY = int.MinValue;
  197.  
  198. // 遍历多边形的顶点,找到最小和最大的x、y坐标
  199. foreach (var vertex in vertices)
  200. {
  201. if (vertex.X < minX)
  202. {
  203. minX = Mathf.CeilToInt(vertex.X);
  204. }
  205. else if (vertex.X > maxX)
  206. {
  207. maxX = Mathf.FloorToInt(vertex.X);
  208. }
  209. if (vertex.Y < minY)
  210. {
  211. minY = Mathf.CeilToInt(vertex.Y);
  212. }
  213. else if (vertex.Y > maxY)
  214. {
  215. maxY = Mathf.FloorToInt(vertex.Y);
  216. }
  217. }
  218.  
  219. var list = new List<Vector2>();
  220. var tryCount = 0;
  221. while (true)
  222. {
  223. if (tryCount >= 2000) //尝试2000次后放弃
  224. {
  225. while (list.Count < count)
  226. {
  227. list.Add(Vector2.Zero);
  228. }
  229. break;
  230. }
  231.  
  232. tryCount++;
  233. var point = new Vector2(RandomRangeInt(minX, maxX), RandomRangeInt(minY, maxY));
  234. foreach (var ps in polygons)
  235. {
  236. var arr = new List<Vector2>();
  237. foreach (var i in ps)
  238. {
  239. arr.Add(vertices[i]);
  240. }
  241.  
  242. if (Utils.IsPointInPolygon(arr, point))
  243. {
  244. tryCount = 0;
  245. list.Add(point);
  246. if (list.Count >= count)
  247. {
  248. return list.ToArray();
  249. }
  250. }
  251. }
  252. }
  253.  
  254. return list.ToArray();
  255. }
  256. }