C#实现伪随机算法之PRD暴击算法

PRD算法是一种常用于游戏中的暴击算法,它介于完全随机和可预测之间。算法通过概率增量C和攻击次数N来计算暴击率。C#代码示例展示了如何根据期望的暴击概率P计算C,以及如何进行攻击模拟以检查暴击发生情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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("----------------------------");
        }
    }
}
PRD (Priority Queues Based on Red-Black Trees) 算法是一种用于高效处理优先级队列的数据结构实现,它利用红黑树的数据结构来保持数据的平衡排序,同时提供插入、删除和查找最小元素等操作的O(log n)时间复杂度。 在C语言实现PRD算法,首先需要了解红黑树的基本性质和操作,包括节点的颜色(红色或黑色)、旋转操作以及颜色调整等。以下是简化的步骤: 1. 定义一个红黑树节点结构,包含值、颜色(红色或黑色)、左子树指针、右子树指针和父节点指针。 ```c typedef struct RBNode { int value; enum Color color; struct RBNode* left; struct RBNode* right; struct RBNode* parent; } RBNode; ``` 2. 实现插入操作(insert),保证插入后的树仍满足红黑树的性质。 ```c void insert(RBNode** root, int value); ``` 3. 实现删除操作(delete),考虑四种情况:删除根、删除非叶子节点、删除叶子节点和仅有一个孩子的节点。 4. 查找最小元素操作(findMin),返回树中的最小元素,同样需要维护红黑树的性质。 ```c RBNode* findMin(RBNode* root); ``` 5. 对于其他常见的优先队列操作,如删除最大元素(deleteMax)、更新元素优先级(adjustPriority)等,都需要对上述操作进行适当的修改或递归应用。 注意,这只是一个简化的概述,实际的C语言实现会更复杂,涉及到大量的细节和边界条件处理。如果你打算编写这样的代码,建议查阅相关资料或源码学习,并确保理解和掌握红黑树的特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

高思宇

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

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

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

打赏作者

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

抵扣说明:

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

余额充值