编辑代码



using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
namespace HelloWorldApplication
{
   public class HelloWorld
   {
      public static void Main()
      {
		// 运行完整系统测试
			ProbabilitySystem.RunSystemTest();
         //string graph = ShowBattleProbabilityGraph(battleKey);
   		 //Console.WriteLine($"\n战斗ID: {battleKey} 的概率分布图:\n{graph}");
      }
   }
	   
	   
	   
	   
	/// <summary>
    /// 多波峰正态分布的配置类
    /// </summary>
    public class PeakConfig
    {
        public int Position { get; set; }    // 波峰位置
        public double Height { get; set; }    // 波峰高度 (0.2-0.7)
        public double Sigma { get; set; }     // 标准差(控制波峰宽度)
    }

    /// <summary>
    /// 战斗概率系统
    /// </summary>
    public static class ProbabilitySystem
    {
        // 存储每场战斗的概率分布图
        private static readonly Dictionary<int, Dictionary<int, double>> _battleProbabilities = new Dictionary<int, Dictionary<int, double>>();
        // 存储每场战斗的波峰信息
        private static readonly Dictionary<int, List<PeakConfig>> _battlePeaks = new Dictionary<int, List<PeakConfig>>();

        #region 概率图生成与管理

        /// <summary>
        /// 生成一场战斗的多波峰正态分布概率图
        /// </summary>
        public static Dictionary<int, double> GenerateProbabilityMap(int minLevel, int maxLevel, int battleKey)
        {
            Dictionary<int, double> probabilityMap = new Dictionary<int, double>();
            Random rand = new Random(battleKey + 123456);

            // 生成3-5个随机波峰
            int peakCount = rand.Next(3, 6);
            List<PeakConfig> peaks = new List<PeakConfig>();

            // 将范围分成几个区域,确保波峰分布相对均匀
            int rangeSize = (maxLevel - minLevel) / peakCount;
            
            for (int i = 0; i < peakCount; i++)
            {
                // 在各自的区域内随机生成波峰位置
                int minPos = minLevel + i * rangeSize;
                int maxPos = minPos + rangeSize;
                
                peaks.Add(new PeakConfig
                {
                    Position = rand.Next(minPos, maxPos),
                    Height = 0.4 + (rand.NextDouble() * 0.3), // 0.2-0.6之间的随机高度
                    Sigma = 10 + (rand.NextDouble() * 10)     // 10-30之间的随机标准差
                });
            }

            // 存储波峰信息
            _battlePeaks[battleKey] = peaks;

            // 为每个等级计算概率
            for (int level = minLevel; level <= maxLevel; level++)
            {
                // 计算所有波峰在该点的概率贡献
                double probability = 0.4; // 基础概率
                foreach (var peak in peaks)
                {
                    // 使用正态分布公式计算每个波峰的贡献
                    double contribution = (peak.Height - 0.4) * 
                        Math.Exp(-Math.Pow(level - peak.Position, 2) / (2 * Math.Pow(peak.Sigma, 2)));
                    probability = Math.Max(probability, 0.4 + contribution);
                }

                // 确保概率在0.25-0.6之间
                probability = Math.Max(0.4, Math.Min(0.7, probability));
                probabilityMap[level] = probability;
            }

            return probabilityMap;
        }

        /// <summary>
        /// 获取或创建概率分布图
        /// </summary>
        public static Dictionary<int, double> GetOrCreateProbabilityMap(int battleKey)
        {
            if (_battleProbabilities.ContainsKey(battleKey))
            {
                return _battleProbabilities[battleKey];
            }
            
            var newMap = GenerateProbabilityMap(1, 200, battleKey);
            _battleProbabilities[battleKey] = newMap;
            return newMap;
        }

        /// <summary>
        /// 清理战斗相关的所有缓存
        /// </summary>
        public static void ClearBattleCache(int battleKey)
        {
            _battleProbabilities.Remove(battleKey);
            _battlePeaks.Remove(battleKey);
        }

        #endregion

        #region 技能触发判断

        /// <summary>
        /// 判断技能是否可以触发
        /// </summary>
        public static bool CanTriggerSkill(int skillLevel, int battleKey)
        {
            var probabilityMap = GetOrCreateProbabilityMap(battleKey);
            if (!probabilityMap.ContainsKey(skillLevel))
                return false;
                
			Random r = new Random();
            Random rand = new Random(battleKey + 123456 + skillLevel + (int)r.Next());
            return rand.NextDouble() <= probabilityMap[skillLevel];
        }

        #endregion

        #region 可视化和测试

        /// <summary>
        /// 显示正态分布概率图
        /// </summary>
        public static string DrawProbabilityGraph(Dictionary<int, double> probabilityMap, int width = 100, int height = 20)
        {
            StringBuilder graph = new StringBuilder();
            // 手动计算最大最小值
			double maxProb = double.MinValue;
			double minProb = double.MaxValue;
			foreach (var prob in probabilityMap.Values)
			{
				if (prob > maxProb) maxProb = prob;
				if (prob < minProb) minProb = prob;
			}
            
            // 计算区间大小
            int totalLevels = probabilityMap.Count;
            int levelsPerColumn = (int)Math.Ceiling((double)totalLevels / width);
            
            // 创建图表数据
            double[] columns = new double[width];
            for (int i = 0; i < width; i++)
            {
                int startLevel = i * levelsPerColumn;
                int endLevel = Math.Min(startLevel + levelsPerColumn, totalLevels);
                
                // 计算这个区间的平均概率
                double sum = 0;
                int count = 0;
                for (int level = startLevel; level < endLevel; level++)
                {
                    if (probabilityMap.ContainsKey(level))
                    {
                        sum += probabilityMap[level];
                        count++;
                    }
                }
                columns[i] = count > 0 ? sum / count : 0;
            }
            
            // 绘制图表标题和概率范围
            graph.AppendLine($"多波峰正态分布概率图");
            graph.AppendLine($"概率范围: {minProb:P0} - {maxProb:P0}");
            graph.AppendLine(new string('-', width + 2));
            
            // 绘制概率分布
            for (int h = height - 1; h >= 0; h--)
            {
                graph.Append('|');
                double threshold = minProb + (maxProb - minProb) * (h / (double)(height - 1));
                
                for (int w = 0; w < width; w++)
                {
                    double value = columns[w];
                    char symbol = ' ';
                    if (value >= threshold)
                    {
                        if (value >= 0.6) symbol = '6';
                        else if (value >= 0.5) symbol = '5';
                        else if (value >= 0.4) symbol = '4';
                        else if (value >= 0.3) symbol = '3';
                        else symbol = '2';
                    }
                    graph.Append(symbol);
                }
                
                if (h == height - 1 || h == 0 || h == height / 2)
                {
                    graph.Append($"| {threshold:P0}");
                }
                else
                {
                    graph.Append("|");
                }
                graph.AppendLine();
            }
            
            graph.AppendLine(new string('-', width + 2));
            
            // 添加等级刻度
            graph.Append(" ");
            for (int i = 0; i < width; i += width / 4)
            {
                int level = i * totalLevels / width;
                string levelStr = level.ToString();
                graph.Append(levelStr.PadRight(width / 4));
            }
            graph.AppendLine(totalLevels.ToString());
            
            return graph.ToString();
        }

        /// <summary>
        /// 运行完整的概率系统测试
        /// </summary>
        public static void RunSystemTest(int battleKey = 0)
        {
            try
            {
                if (battleKey == 0)
                {
                    battleKey = 223311;
                }

                Console.WriteLine("\n========= 开始概率系统测试 =========\n");

                // 测试参数
                int testCount = 1000;
                int[] testLevels = { 10, 50, 100, 150, 200 };

                // 生成并显示概率分布图
                var probabilityMap = GetOrCreateProbabilityMap(battleKey);
                string graph = DrawProbabilityGraph(probabilityMap);
                Console.WriteLine($"战斗ID: {battleKey} 的概率分布图:\n{graph}");

                // 显示波峰信息
                if (_battlePeaks.ContainsKey(battleKey))
                {
                    var peaks = _battlePeaks[battleKey];
                    Console.WriteLine("\n波峰信息:");
                    for (int i = 0; i < peaks.Count; i++)
                    {
                        Console.WriteLine($"波峰 {i + 1}: 位置={peaks[i].Position}, 高度={peaks[i].Height:P0}, 标准差={peaks[i].Sigma:F1}");
                    }
                }

                // 测试每个等级点
                Console.WriteLine("\n开始触发概率测试:");
                foreach (int level in testLevels)
                {
                    TestSpecificLevel(level, battleKey, testCount);
                }

                // 连续等级概率分布测试
                Console.WriteLine("\n连续等级概率分布测试 (每10级采样):");
                for (int level = 1; level <= 200; level += 10)
                {
                    if (probabilityMap.ContainsKey(level))
                    {
                        Console.WriteLine($"等级 {level,3}: {new string('█', (int)(probabilityMap[level] * 50))} {probabilityMap[level]:P2}");
                    }
                }

                Console.WriteLine("\n========= 概率系统测试完成 =========\n");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"测试过程中发生错误: {ex.Message}\n{ex.StackTrace}");
            }
        }

        /// <summary>
        /// 测试特定等级的触发概率
        /// </summary>
        public static void TestSpecificLevel(int level, int battleKey, int testCount = 100)
        {
            var probabilityMap = GetOrCreateProbabilityMap(battleKey);
            double theoreticalProb = probabilityMap[level];
            int successCount = 0;

            for (int i = 0; i < testCount; i++)
            {
                if (CanTriggerSkill(level, battleKey))
                {
                    successCount++;
                }
            }

            double actualProb = (double)successCount / testCount;

            Console.WriteLine($"\n等级 {level} 测试结果:");
            Console.WriteLine($"理论概率: {theoreticalProb:P2}");
            Console.WriteLine($"实际触发: {successCount}/{testCount} ({actualProb:P2})");
            Console.WriteLine($"误差: {Math.Abs(actualProb - theoreticalProb):P2}");
        }

        #endregion
    }

}