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暴击算法

C#实现PRD算法

环境:使用VisualStudio创建控制台应用
代码如下:

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("----------------------------");
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高思宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值