Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / common / WeightRandom.cs
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4.  
  5. /// <summary>
  6. /// 带有权重的随机值处理类
  7. /// </summary>
  8. public class WeightRandom
  9. {
  10. private (float, int)[] _prepareAdRewardWeight;
  11. private SeedRandom _random;
  12.  
  13. public WeightRandom(SeedRandom random)
  14. {
  15. _random = random;
  16. }
  17.  
  18. /// <summary>
  19. /// 设置随机数生成器
  20. /// </summary>
  21. public void SetSeedRandom(SeedRandom random)
  22. {
  23. _random = random;
  24. }
  25. /// <summary>
  26. /// 初始化权重列表
  27. /// </summary>
  28. public void InitAdRewardWeight(int[] weightList)
  29. {
  30. var total = weightList.Sum();
  31. var length = weightList.Length;
  32. var avg = 1f * total / length;
  33. var smallAvg = new List<(float, int)>();
  34. var bigAvg = new List<(float, int)>();
  35. for (int i = 0; i < weightList.Length; i++)
  36. {
  37. (weightList[i] > avg ? bigAvg : smallAvg).Add((weightList[i], i));
  38. }
  39.  
  40. _prepareAdRewardWeight = new (float, int)[weightList.Length];
  41. for (int i = 0; i < weightList.Length; i++)
  42. {
  43. if (smallAvg.Count > 0)
  44. {
  45. if (bigAvg.Count > 0)
  46. {
  47. _prepareAdRewardWeight[smallAvg[0].Item2] = (smallAvg[0].Item1 / avg, bigAvg[0].Item2);
  48. bigAvg[0] = (bigAvg[0].Item1 - avg + smallAvg[0].Item1, bigAvg[0].Item2);
  49. if (avg - bigAvg[0].Item1 > 0.0000001f)
  50. {
  51. smallAvg.Add(bigAvg[0]);
  52. bigAvg.RemoveAt(0);
  53. }
  54. }
  55. else
  56. {
  57. _prepareAdRewardWeight[smallAvg[0].Item2] = (smallAvg[0].Item1 / avg, smallAvg[0].Item2);
  58. }
  59.  
  60. smallAvg.RemoveAt(0);
  61. }
  62. else
  63. {
  64. _prepareAdRewardWeight[bigAvg[0].Item2] = (bigAvg[0].Item1 / avg, bigAvg[0].Item2);
  65. bigAvg.RemoveAt(0);
  66. }
  67. }
  68. }
  69.  
  70. /// <summary>
  71. /// 获取下一个随机索引
  72. /// </summary>
  73. public int GetRandomIndex()
  74. {
  75. var randomNum = _random.RandomDouble() * _prepareAdRewardWeight.Length;
  76. var intRan = (int)Math.Floor(randomNum);
  77. var p = _prepareAdRewardWeight[intRan];
  78. if (p.Item1 > randomNum - intRan)
  79. {
  80. return intRan;
  81. }
  82. else
  83. {
  84. return p.Item2;
  85. }
  86. }
  87. }