ProbabilityGenerator

来源:互联网 发布:郑州做seo的工资 编辑:程序博客网 时间:2024/06/05 10:42
 /// <summary>
    /// 概率发生器使用的信息类
    /// </summary>
    [System.Serializable]
    public class ProbabilityInfo
    {
        /// <summary>
        /// 用于 Editor中列表项的显示.
        /// </summary>
        public string name;

        /// <summary>
        /// 对应的 prefab.
        /// </summary>
        public GameObject prefab;

        /// <summary>
        /// 概率,逐次概率发生算法使用.
        /// </summary>
        [Range(0, 1)]
        public float probability = 1;

        /// <summary>
        /// 权重,圆桌理论(ProbabilityGenerator.TableCoverage)算法使用
        /// </summary>
        public int weight;

    }


 /// <summary>
    /// 概率发生器
    /// </summary>
    public static class ProbabilityGenerator
    {
        /// <summary>
        /// 百分比 概率测试
        /// </summary>
        /// <param name="ratio"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static bool Test(int ratio, int max = 100)
        {
            if (ratio == 0 || max == 0)
                return false;


            return Test((float)ratio / (float)max);
        }


        /// <summary>
        /// 测试[0,max]内的随机取值 > ratio ?
        /// </summary>
        /// <param name="ratio"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static bool Test(float ratio = 0.5f, float max = 1)
        {
            if (max <= 0)
                max = 1;
            var random = Random.Range(0f, max);
            return random <= ratio;
        }


        /// <summary>
        /// 逐次测试概率发生算法.
        /// </summary>
        /// <param name="infos"></param>
        /// <returns></returns>
        public static ProbabilityInfo StepJudge(ProbabilityInfo[] infos)
        {
            if (infos.Length <= 0)
                return null;


            //1 test probability
            foreach (var p in infos)
            {
                if (Test(p.probability))
                {
                    return p;
                }
            }
            //2 random select one;
            return infos[Random.Range(0, infos.Length)];
        }


        /// <summary>
        /// 使用weight进行圆桌覆盖算法判断
        /// </summary>
        /// <param name="infos"></param>
        /// <returns></returns>
        public static ProbabilityInfo TableCoverage(ProbabilityInfo[] infos)
        {
            if (infos == null)
            {
                return null;
            }


            var sum = (from item in infos select item.weight).Sum();
            if (sum == 0)
            {
                return StepJudge(infos);
            }


            var index = Random.Range(0, sum);


            int start = 0;
            var q = from item in infos select new { Start = start, End = start + item.weight, Info = item };
            foreach (var item in q)
            {
                start += item.Info.weight;
                if (item.Start < index && item.End > index)
                {
                    return item.Info;
                }
            }
            return infos[Random.Range(0, infos.Length)];
        }

    }