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. /// <param name="polygonDataList">碰撞区域数据</param>
  188. /// <param name="count">需要随机点的数量</param>
  189. public Vector2[] GetRandomPositionInPolygon(List<NavigationPolygonData> polygonDataList, int count)
  190. {
  191. var minX = int.MaxValue;
  192. var maxX = int.MinValue;
  193. var minY = int.MaxValue;
  194. var maxY = int.MinValue;
  195. var outCount = 0;
  196.  
  197. // 遍历多边形的顶点,找到最小和最大的x、y坐标
  198. foreach (var navigationPolygonData in polygonDataList)
  199. {
  200. if (navigationPolygonData.Type == NavigationPolygonType.Out)
  201. {
  202. outCount++;
  203. }
  204. foreach (var vertex in navigationPolygonData.GetPoints())
  205. {
  206. if (vertex.X < minX)
  207. {
  208. minX = Mathf.CeilToInt(vertex.X);
  209. }
  210. else if (vertex.X > maxX)
  211. {
  212. maxX = Mathf.FloorToInt(vertex.X);
  213. }
  214. if (vertex.Y < minY)
  215. {
  216. minY = Mathf.CeilToInt(vertex.Y);
  217. }
  218. else if (vertex.Y > maxY)
  219. {
  220. maxY = Mathf.FloorToInt(vertex.Y);
  221. }
  222. }
  223. }
  224.  
  225. var list = new List<Vector2>();
  226. while (true)
  227. {
  228. var flag = outCount == 0;
  229. var point = new Vector2(RandomRangeInt(minX, maxX), RandomRangeInt(minY, maxY));
  230. foreach (var navigationPolygonData in polygonDataList)
  231. {
  232. if (navigationPolygonData.Type == NavigationPolygonType.Out)
  233. {
  234. if (!flag && Utils.IsPointInPolygon(navigationPolygonData.GetPoints(), point))
  235. {
  236. flag = true;
  237. }
  238. }
  239. else
  240. {
  241. if (flag && Utils.IsPointInPolygon(navigationPolygonData.GetPoints(), point))
  242. {
  243. flag = false;
  244. }
  245. }
  246. }
  247.  
  248. if (flag)
  249. {
  250. list.Add(point);
  251. if (list.Count >= count)
  252. {
  253. return list.ToArray();
  254. }
  255. }
  256. }
  257. }
  258. }