【结构与算法】—— 游戏概率常用算法整理 | 游戏中的常见概率设计分析

news/2024/5/18 12:53:46 标签: 游戏, 游戏引擎, 游戏程序, 算法, 概率论

  • 📢博客主页:肩匣与橘
  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
  • 📢本文由肩匣与橘编写,首发于CSDN🙉
  • 📢生活依旧是美好而又温柔的,你也是✨ 

目录

一、随机数生成

二、概率分布

2.1均匀分布

2.2正态分布

2.3泊松分布

三、随机事件触发

3.1固定概率触发

3.2基于概率分布的触发

3.3基于条件的触发

四、常见概率算法

4.1概率表

4.2权重随机

4.3概率分布函数

五、真随机和伪随机


       在游戏开发中,概率技术是非常重要的一部分。它涉及到游戏中的随机事件,如掉落物品、怪物出现、技能触发等。正确使用概率技术可以使游戏更加有趣和具有挑战性。

一、随机数生成

       在游戏中,随机数生成是非常常见的。我们需要生成随机数来模拟各种随机事件。在C++中,我们可以使用rand函数来生成随机数。rand函数返回一个介于0和RAND_MAX(通常是32767)之间的整数。我们可以使用模运算和加法来生成指定范围内的随机数。 例如,我们要生成1到100之间的随机数,可以使用以下代码:

int randomNumber = rand() % 100 + 1;

二、概率分布

       在游戏中,我们经常需要使用不同的概率分布来模拟各种随机事件。以下是一些常见的概率分布:

2.1均匀分布

       均匀分布是最基本的概率分布之一。在均匀分布中,每个数字出现的概率是相等的。我们可以使用rand函数来生成均匀分布。 例如,我们要生成1到6之间的随机数,可以使用以下代码:

int randomNumber = rand() % 6 + 1;

2.2正态分布

       正态分布是另一个常见的概率分布。在正态分布中,大多数数字集中在平均值附近,并且随着距离平均值的增加而变得越来越少。我们可以使用Box-Muller转换来生成正态分布。 以下是一个生成具有指定平均值和标准差的正态分布的代码示例:

double normalRandomNumber(double mean, double stddev)
{
    static double n2 = 0.0;
    static int n2_cached = 0;
    if (!n2_cached)
    {
        double x, y, r;
        do
        {
            x = 2.0*rand()/RAND_MAX - 1;
            y = 2.0*rand()/RAND_MAX - 1;
            r = x*x + y*y;
        }
        while (r == 0.0 || r > 1.0);
        {
            double d = sqrt(-2.0*log(r)/r);
            double n1 = x*d;
            n2 = y*d;
            double result = n1*stddev + mean;
            n2_cached = 1;
            return result;
        }
    }
    else
    {
        n2_cached = 0;
        return n2*stddev + mean;
    }
}

2.3泊松分布

       泊松分布是用于模拟随机事件发生的数量的分布。在泊松分布中,事件发生的概率是相等的,而事件发生的次数是随机的。我们可以使用以下代码来生成泊松分布:

int poissonRandomNumber(double lambda)
{
    double L = exp(-lambda);
    double p = 1.0;
    int k = 0;
    do
    {
        k++;
        double u = rand()/((double)RAND_MAX + 1);
        p *= u;
    }
    while (p > L);
    return k - 1;
}

三、随机事件触发

       在游戏中,我们经常需要触发各种随机事件,如掉落物品、怪物出现、技能触发等。我们可以使用概率技术来控制这些事件的触发概率。以下是一些常见的随机事件触发技术:

3.1固定概率触发

       在固定概率触发中,我们使用一个固定的概率来控制事件的触发。例如,我们可以使用以下代码来控制一个事件以50%的概率触发:

bool shouldTrigger = (rand() % 2 == 0);
if (shouldTrigger)
{
    // 触发事件
}

3.2基于概率分布的触发

       在基于概率分布的触发中,我们使用一个特定的概率分布来控制事件的触发。例如,我们可以使用以下代码来控制一个事件以正态分布的概率触发:

double mean = 0.5;
double stddev = 0.1;
double randomNumber = normalRandomNumber(mean, stddev);
if (randomNumber > 0 && randomNumber < 1)
{
    // 触发事件
}

3.3基于条件的触发

       在基于条件的触发中,我们使用一个或多个条件来控制事件的触发。例如,我们可以使用以下代码来控制一个事件仅在满足一定条件时触发:

bool condition1 = true;
bool condition2 = false;
if (condition1 && !condition2)
{
    // 触发事件
}

四、常见概率算法

4.1概率表

       概率表是一种最简单的概率算法。它将所有的可能结果列出,并为每个结果分配一个概率值。然后,使用随机数生成器来生成一个随机数,并根据随机数选择一个结果。 例如,我们有一个掉落物品的概率表,其中掉落物品的概率分别为30%、20%和10%:

物品概率
物品A30%
物品B20%
物品C10%

       我们可以使用随机数生成器来生成一个随机数,例如在Java中,我们可以使用以下代码:

import java.util.Random;
public class Example {
    public static void main(String[] args) {
        Random random = new Random();
        // 生成一个随机整数
        int randomInt = random.nextInt(100);
        // 判断掉落的物品
        if (randomInt < 30) {
            // 掉落物品A
        } else if (randomInt < 50) {
            // 掉落物品B
        } else {
            // 掉落物品C
        }
    }
}

       上述代码中,我们生成一个0到99的随机整数,并根据随机数选择掉落的物品。

4.2权重随机

       权重随机是一种更加高级的概率算法。它将所有的可能结果列出,并为每个结果分配一个权重值。然后,使用随机数生成器来生成一个随机数,并根据权重值选择一个结果。 例如,我们有一个掉落物品的权重表,其中掉落物品的权重分别为3、2和1:

物品权重
物品A3
物品B2
物品C1

       我们可以使用随机数生成器来生成一个随机数,并根据权重值选择掉落的物品,例如在Java中,我们可以使用以下代码:

import java.util.Random;
public class Example {
    public static void main(String[] args) {
        Random random = new Random();
        // 生成一个随机整数
        int randomInt = random.nextInt(6);
        // 判断掉落的物品
        if (randomInt < 3) {
            // 掉落物品A
        } else if (randomInt < 5) {
            // 掉落物品B
        } else {
            // 掉落物品C
        }
    }
}

       上述代码中,我们生成一个0到5的随机整数,并根据权重值选择掉落的物品。

4.3概率分布函数

       概率分布函数是一种更加复杂的概率算法。它通过一个数学函数来计算每个结果的概率值。然后,使用随机数生成器来生成一个随机数,并根据概率分布函数计算出选择的结果。 例如,我们有一个技能释放的概率分布函数,其中释放技能的概率随时间逐渐增加。我们可以使用以下的代码计算释放技能的概率,其中,time表示时间,a表示技能开始释放的时间,k表示技能释放的速率。我们可以使用随机数生成器来生成一个随机数,并使用概率分布函数计算释放技能的概率,我们可以使用以下代码:

import java.util.Random;
public class Example {
    public static void main(String[] args) {
        Random random = new Random();
        // 生成一个随机浮点数
        double randomDouble = random.nextDouble();
        // 计算释放技能的概率
        double time = getTime();
        double a = 0.0;
        double k = 1.0;
        double probability = 1.0 / (1.0 + Math.exp(-k * (time - a)));
        // 判断是否释放技能
        if (randomDouble < probability) {
            // 释放技能
        }
    }
    private static double getTime() {
        // 获取当前时间
        return 0.0;
    }
}

       上述代码中,我们生成一个0到1的随机浮点数,并根据概率分布函数计算释放技能的概率。如果随机数小于概率值,我们就释放技能。

五、真随机和伪随机

       在游戏开发中,概率是一个非常重要的概念。我们通常使用随机数进行生成,例如怪物掉落物品、技能释放概率等等。然而,在使用随机数时,开发者需要考虑到真随机和伪随机的问题。        伪随机数生成器(PRNG)是一种算法,它可以生成一个序列的数字,这些数字看起来像是随机的,但实际上是按照算法生成的。在PRNG中,种子值是非常重要的。如果我们使用相同的种子值,我们将会获得相同的随机数序列。

       真随机数生成器(TRNG)是基于物理事件的,例如大气噪声、微粒衰变等等。它们可以生成真正的随机数,因为它们是由不可预测的物理事件生成的。然而,在大多数情况下,我们可以使用伪随机数生成器来模拟真随机数。

       可以说,真随机是一种自然的随机机制,用代码来实现也非常容易,只需要用一个随机数与一个常量进行比较,根据大于小于等于分别触发不同的结果就行了。例如:掷色子,掷到到的值大于3触发什么奖励,小于三又是什么奖励,等于三又是另一种奖励。而伪随机则是人为创造出来的一种机制,他需要程序员写下更多的代码,也需要数值设计者做更多的计算。例如游戏的抽奖机制,当玩家抽到第90次还没有最好品质的奖励,那么第九十次必定获得该奖励,同时在获得该道具后,概率又恢复初始;亦或者是每次没有获得该道具,概率就增加,到第90次,概率是100%,必得该奖励,同时在获得该奖励后,概率又恢复初始。


       游戏开发中,概率技术是非常重要的一部分。我们可以使用随机数生成、概率分布和随机事件触发等技术来模拟各种随机事件,使游戏更加有趣和挑战性。在实际开发中,我们应该根据具体情况选择适当的技术,并进行充分的测试和优化,以确保游戏的质量和稳定性。


http://www.niftyadmin.cn/n/315728.html

相关文章

AI换脸系统开发源码交付

AI换脸系统软件的发展趋势包括以下几个方面&#xff1a; 定制化和智能化&#xff1a;随着用户需求的不断增加&#xff0c;AI换脸系统将向更加定制化和智能化的方向发展&#xff0c;通过数据分析和用户画像等手段&#xff0c;为用户提供更加个性化的服务。 多模态应用&a…

【游戏逆向】《创世战车》玩家遍历分析

对于这种FPS游戏来说&#xff0c;玩家的血量并不是很关键&#xff0c;不过想分析玩家对象内的其他信息&#xff0c;还是要从血量作为突破口的。 但是由于试驾场是很少有发包的&#xff0c;包括战车的攻击等等&#xff0c;所以只能通过正常匹配战斗进行扫描。又由于匹配模式中没…

Python: 导入或执行python源文件的几种方法

目录 概要 方法1&#xff1a;import 方法2&#xff1a;exec() 方法3&#xff1a;os.system() 概要 本文介绍python中导入或执行python源文件&#xff08;通常是从另一个python源文件中&#xff09;的几种常用方法。包括import, exec(), os.system()等。 方法1&#xff1a;im…

(四)深入理解Bluez协议栈之“GAP Profile”

目录 前言: 概述: 参考代码: mgmt接口: bt_hci*接口: 说明:

Jetpack之Navigation技术解密

Navigation是什么 官方的话&#xff1a; Navigation 是一个框架&#xff0c;用于在 Android 应用中的“目标”之间导航&#xff0c;该框架提供一致的 API&#xff0c;无论目标是作为 Fragment、Activity 还是其他组件实现。 自己的话&#xff1a; Navigation是管理Fragment…

JavaEEFoundation

JavaEEFoundation 一. JavaWeb常用API1.1 BeanUtils 对象拷贝1.1.1 copyProperties(a,b)一. JavaWeb常用API 1.1 BeanUtils 对象拷贝 import org.springframework.beans.BeanUtils; @NoArgsConstructor @AllArgsConstructor @Data class A {private Long id;

第十二届蓝桥杯青少组省赛Python真题,包含答案

目录 一、选择题 二、编程题 第十二届蓝桥杯青少组省赛Python真题 一、选择题 第 1 题 单选题 设s="Hello Lan Qiao,执行print(s[4:11])输出的结果为 () 答案:D 第 2 题 单选题 循环语句for iin range (8,4,2) : 执行了几次循环 ()

RK3588 设备树pinctrl gpio子系统解析,解决GPIO无法正确拉高拉低的问题,RK3588设备树详解

一、RK3588设备树结构 firefly的官方说明文档RK3588gpio系统说明 function {group {rockchip,pin <bank gpio func &ref>;}; };其中&#xff0c;bank是所属的组&#xff0c;Core-3588J 有 5 组 GPIO bank&#xff1a;GPIO0-GPIO4&#xff0c;每组又以 A0-A7, B0-B…