using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
namespace HelloWorldApplication
{
public class HelloWorld
{
public static void Main()
{
ProbabilitySystem.RunSystemTest();
}
}
public class PeakConfig
{
public int Position { get; set; }
public double Height { get; set; }
public double Sigma { get; set; }
}
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 概率图生成与管理
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);
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),
Sigma = 10 + (rand.NextDouble() * 10)
});
}
_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);
}
probability = Math.Max(0.4, Math.Min(0.7, probability));
probabilityMap[level] = probability;
}
return probabilityMap;
}
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;
}
public static void ClearBattleCache(int battleKey)
{
_battleProbabilities.Remove(battleKey);
_battlePeaks.Remove(battleKey);
}
#endregion
#region 技能触发判断
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 可视化和测试
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();
}
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}");
}
}
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
}
}