C#은 의사 무작위 알고리즘의 PRD 중요 공격 알고리즘을 구현합니다.

PRD 알고리즘 소개

  PRD 의사 난수 알고리즘은 게임에서 치명타 알고리즘으로 자주 사용됩니다. 이 알고리즘은 치명타 발생을 전적으로 운에 의존하지도 않고 정확하게 예측할 수도 없게 하며 둘 사이의 절충안입니다.
  PRD 알고리즘의 표현은 매우 간단합니다.

P(N) = C * N

  N은 현재 공격 횟수, P(N)은 현재 공격의 치명타율, C는 확률 증가분을 나타낸다. 공격이 치명타로 이어지면 N을 1로 재설정해야 합니다. 이 공격이 치명타로 이어지지 않으면 N + 1입니다.
  C는 실제 확률 P를 통해 직접 구할 수 있는데, 즉 C와 실제 확률 사이에는 일대일 대응이 존재한다.예를 들어 실제 임계 확률 P가 0.5라면 C는 항상 0.3이다.

구체적인 알고리즘은 다음 링크에 자세히 소개되어 있습니다. PRD crit 알고리즘, 게임에서 흔히 사용되는 의사 랜덤 알고리즘

C#은 PRD 알고리즘을 구현합니다.

환경: Visual Studio를 사용하여 콘솔 애플리케이션을 생성합니다.
코드는 다음과 같습니다.

class PRD
{
    
    
    //总概率
    public double p;
    //概率增量
    public double c;
    // 根据 传入 C 值,计算该C值下,最小暴击范围的平均暴击率
    private double PFromC(double c)
    {
    
    
        double dCurP = 0d;
        double dPreSuccessP = 0d;
        double dPE = 0;
        int nMaxFail = (int)Math.Ceiling(1d / c);
        for (int i = 1; i <= nMaxFail; ++i)
        {
    
    
            dCurP = Math.Min(1d, i * c) * (1 - dPreSuccessP);
            dPreSuccessP += dCurP;
            dPE += i * dCurP;
        }
        return 1d / dPE;
    }
    // 根据实际暴击概率P,计算概率增量C
    public double CFromP(double p)
    {
    
    
        double dUp = p;
        double dLow = 0d;
        double dMid = p;
        double dPLast = 1d;
        while (true)
        {
    
    
            dMid = (dUp + dLow) / 2d;
            double dPtested = PFromC(dMid);
            if (Math.Abs(dPtested - dPLast) <= 0.00005d) break;
            if (dPtested > p) dUp = dMid;
            else dLow = dMid;
            dPLast = dPtested;
        }
        return dMid;
    }
    //当前攻击的次数
    private int attackCount = 1;
    //返回是否暴击,如果没暴击则攻击次数加1,如果暴击了则攻击次数重置为1
    public bool IsCriticalHit()
    {
    
    
        if (new Random().Next(1, 101) <= (int)(c * 100d) * attackCount)
        {
    
    
            attackCount = 1;
            return true;
        }
        else
        {
    
    
            attackCount++;
            return false;
        }
    }
}
class Program
{
    
    
    static void Main(string[] args)
    {
    
    
        PRD prd = new PRD();
        //设置暴击率为0.5
        prd.p = 0.5;
        Console.WriteLine("暴击率为" + (int)(prd.p * 100d) + "%");
        //计算概率增量
        prd.c = prd.CFromP(prd.p);
        //按n键模拟攻击一次
        int iCriticalHitCount = 0, iTotolCount = 0;
        while (Console.ReadKey().Key == ConsoleKey.N)//检测到玩家按N键
        {
    
    
            if (prd.IsCriticalHit())
            {
    
    
                iCriticalHitCount++;
                Console.WriteLine("暴击!!!!!!!!");
            }
            else
            {
    
    
                Console.WriteLine("未暴击");
            }
            iTotolCount++;
            Console.WriteLine("总次数:" + iTotolCount + ",暴击次数" + iCriticalHitCount +
                ",总暴击率:" + (int)((double)iCriticalHitCount / (double)iTotolCount * 100d) + "%");
            Console.WriteLine("----------------------------");
        }
    }
}

Supongo que te gusta

Origin blog.csdn.net/qq_44284055/article/details/129815617
Recomendado
Clasificación