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. /// <summary>
  18. /// 初始化权重列表
  19. /// </summary>
  20. public void InitAdRewardWeight(int[] weightList)
  21. {
  22. var total = weightList.Sum();
  23. var length = weightList.Length;
  24. var avg = 1f * total / length;
  25. var smallAvg = new List<(float, int)>();
  26. var bigAvg = new List<(float, int)>();
  27. for (int i = 0; i < weightList.Length; i++)
  28. {
  29. (weightList[i] > avg ? bigAvg : smallAvg).Add((weightList[i], i));
  30. }
  31.  
  32. _prepareAdRewardWeight = new (float, int)[weightList.Length];
  33. for (int i = 0; i < weightList.Length; i++)
  34. {
  35. if (smallAvg.Count > 0)
  36. {
  37. if (bigAvg.Count > 0)
  38. {
  39. _prepareAdRewardWeight[smallAvg[0].Item2] = (smallAvg[0].Item1 / avg, bigAvg[0].Item2);
  40. bigAvg[0] = (bigAvg[0].Item1 - avg + smallAvg[0].Item1, bigAvg[0].Item2);
  41. if (avg - bigAvg[0].Item1 > 0.0000001f)
  42. {
  43. smallAvg.Add(bigAvg[0]);
  44. bigAvg.RemoveAt(0);
  45. }
  46. }
  47. else
  48. {
  49. _prepareAdRewardWeight[smallAvg[0].Item2] = (smallAvg[0].Item1 / avg, smallAvg[0].Item2);
  50. }
  51.  
  52. smallAvg.RemoveAt(0);
  53. }
  54. else
  55. {
  56. _prepareAdRewardWeight[bigAvg[0].Item2] = (bigAvg[0].Item1 / avg, bigAvg[0].Item2);
  57. bigAvg.RemoveAt(0);
  58. }
  59. }
  60. }
  61.  
  62. /// <summary>
  63. /// 获取下一个随机索引
  64. /// </summary>
  65. public int GetRandomIndex()
  66. {
  67. var randomNum = _random.RandomDouble() * _prepareAdRewardWeight.Length;
  68. var intRan = (int)Math.Floor(randomNum);
  69. var p = _prepareAdRewardWeight[intRan];
  70. if (p.Item1 > randomNum - intRan)
  71. {
  72. return intRan;
  73. }
  74. else
  75. {
  76. return p.Item2;
  77. }
  78. }
  79. }