前言

当我最初写游戏时,我经常使用标准Random()函数,然后写一堆if和else条件来我获得预期结果。如果结果不太好,我会写更多的条件进行过滤或者筛选,直到我觉得游戏变得有趣。最近我发现有更好的方法。内置的Random类并没有问题,问题是使用内置的Random类很难达到我们的预期效果。

现实生活中,以抛硬币为例,时而会抛出连续多次花或者字。那么如果在游戏中,可能表现为多次连续的暴击或是硬直,尽管有时暴击和硬直的概率很低,但依旧有可能连续出现,让人感觉诡异。那么为了解决类似的问题,前辈们想了很多种方法,比如说特殊值过滤等等。我们今天介绍的是Shuffle Bag技术,可以让你的随机数不那么随机,由你掌控。

什么是Shuffle Bag呢?

Shuffle Bag是一项让我们可以控制随机数分布的技术。

其主要原理为:

  • 设计一个特定分布数值的集合。
  • 把集合中数值转载至背包中。
  • 将背包中数值随机打乱。
  • 从背包中以任意顺序(从前往后,从后往前都无所谓)一个一个的抽取数值,抽完不放回,直到背包为空。
  • 背包为空后,将数据放回,并重新打乱,之后循环利用。
不难看出,Shuffle Bag 特性如下:
  1. 不会产生集合之外的数据。
  2. 它仍然具有随机性,元素出现的顺序还是随机的。
  3. 非重复抽取,如果数据集中某个元素只有一个,至多连续出现两次。

如何实现Shuffle Bag?

原文使用C#,这里使用Unity C#和泛型,大家可以很方便的转译为其他语言。实现并不是先把整个背包先随机打乱,而是每次抽取时,才进行一次随机交换,这样做可以分摊性能,不至于在背包数据较多时,打乱背包消耗某帧过多性能。
using System.Collections.Generic;

using UnityEngine;

public class ShuffleBag<T> {

    private List<T> data;
private T currentItem;
private int currentPosition = -1; private int Capacity { get { return data.Capacity; } }
public int Size { get { return data.Count; } } public ShuffleBag(int initCapacity)
{
data = new List<T>(initCapacity);
} public void Add(T item, int amount)
{
for (int i = 0; i < amount; i++)
data.Add(item); currentPosition = Size - 1;
} public T Next()
{
if (currentPosition < 1)
{
currentPosition = Size - 1;
currentItem = data[0]; return currentItem;
} var pos = Random.Range(0,currentPosition);
currentItem = data[pos];
data[pos] = data[currentPosition];
data[currentPosition] = currentItem;
currentPosition--; return currentItem;
}
}

  

如何使用Shuffle Bag?

在我的项目中,我希望NPC播放受伤动画的概率为十分之一,并且我不希望看到他偶尔连续播放受伤动画多次,也不想长时间不播放受伤动画。

  ShuffleBag<bool> hurtBag = new ShuffleBag<bool>(10);
hurtBag.Add(false, 9);
hurtBag.Add(true, 1);
  //当触发受伤时,调用以下逻辑
if(hurtBag.Next())
{
Play();
}

  

附录

附上参考的原文链接 Shuffle Bags: Making Random() Feel More Random  英文好的同学可以直接看原文 。另外,这个原文题目有些让人疑惑,所以我的译文标题做了一些更改。

Shuffle Bags让你的随机不那么随机的更多相关文章

  1. 随机采样和随机模拟:吉布斯采样Gibbs Sampling实现文档分类

    http://blog.csdn.net/pipisorry/article/details/51525308 吉布斯采样的实现问题 本文主要说明如何通过吉布斯采样进行文档分类(聚类),当然更复杂的实 ...

  2. Atitit.并发测试解决方案(2) -----获取随机数据库记录 随机抽取数据 随机排序 原理and实现

    Atitit.并发测试解决方案(2) -----获取随机数据库记录 随机抽取数据 随机排序 1. 应用场景 1 2. 随机抽取数据原理 1 3. 常用的实现方法:::数据库随机函数 1 4. Mssq ...

  3. 随机采样和随机模拟:吉布斯采样Gibbs Sampling实现高斯分布参数推断

    http://blog.csdn.net/pipisorry/article/details/51539739 吉布斯采样的实现问题 本文主要说明如何通过吉布斯采样来采样截断多维高斯分布的参数(已知一 ...

  4. 5随机到7随机的C++实现

    一.5随机到7随机 //给定条件 int Rand1To5(){ + ; } //实现代码,使用插空法和筛的过程 int Rand1To7(){ ; do{ tmp = (Rand1To5() - ) ...

  5. 随机总数字里面选取随机数字进行随机排序案例(JAVA实现)

    随机总数字里面选取随机数字进行随机排序案例,案例如下: 代码code: package com.sec; import java.util.Arrays; import java.util.Scann ...

  6. scrapy抓取拉勾网职位信息(六)——反爬应对(随机UA,随机代理)

    上篇已经对数据进行了清洗,本篇对反爬虫做一些应对措施,主要包括随机UserAgent.随机代理. 一.随机UA 分析:构建随机UA可以采用以下两种方法 我们可以选择很多UserAgent,形成一个列表 ...

  7. sql server随机排序和随机取出n条数据

    问题:博主在2010-2011学年,广东技术师范大学大四的时候,去过红海人力集团面试数据库职位,很清楚记得当时有一道笔试题目是:编写sql从表里面随机取出10条记录. 解决方案:在sql server ...

  8. 7. 进行图片的数据补全和增强(随机亮度,随机饱和度,随机翻转) Image.open(进行图片的读入) 2.ImageEnhance.Brightness(亮度变化) 3.ImageEnhance.Contrast(饱和度变化) 4.enhance_image.transpose(图片随机翻转) 5.enhance_image.save(进行图片保存)

    1.Image.open(image_path)  进行图片的打开 参数说明:image_path 表示图片的路径 2. ImageEnhance.Brightness(image)  # 进行图片的 ...

  9. JMeter - 生成随机数/随机字符串/随机变量/随机日期

    1. Random - 随机数 1.1 作用 1.2 声明 1.3 例子 2. __RandomDate - 随机日期 2.1 作用 2.2 声明参数 2.3 例子 3. RandomString - ...

随机推荐

  1. html5小结

    本文提到的HTML5仅仅指于2014年完成新一代的HTML标准. html5主要在以下方面做了改变. 1.新增标签 新增语义化标签. <header> 定义 section 或 page ...

  2. Nginx变量.md

    ngx_http_core_module ngx_http_core_module模块支持名称与Apache服务器变量匹配的嵌入式变量. 首先,这些是表示客户请求头字段的变量,例如$ http_use ...

  3. python第二十课——math模块中常用的函数

    属性: e:自然数 pi:圆周率 函数: ceil():向上取整 floor():向下取整 sqrt():开平方根 radians():角度转弧度 degrees():弧度转角度 import mat ...

  4. BZOJ3160:万径人踪灭(FFT,Manacher)

    Solution $ans=$回文子序列$-$回文子串的数目. 后者可以用$manacher$直接求. 前者设$f[i]$表示以$i$为中心的对称的字母对数. 那么回文子序列的数量也就是$\sum_{ ...

  5. 3282. Tree【LCT】

    Description 给定N个点以及每个点的权值,要你处理接下来的M个操作. 操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和 ...

  6. 20145203JAVA课程总结

    20145203盖泽双 <Java程序设计>课程总结 课程总结 (按顺序)每周读书笔记链接汇总 调查问卷:http://www.cnblogs.com/GZSdeboke/p/524832 ...

  7. flex布局中flex-shrink的计算规则

    下面代码来自MDN html部分: <p>the width of content is 500px, flex-basic of flex item is 120px.</p> ...

  8. Docker实战(八)之Web服务与应用

    1.Apache 官方提供了名为httpd的Apache镜像,可以作为基础web服务镜像 Dockerfile(安装apache2) FROM httpd:2.4 COPY ./public-html ...

  9. 《Python核心编程》第二版第五章答案

    本人python新手,答案自己做的,如果有问题,欢迎大家评论和讨论! 更新会在本随笔中直接更新. 5-1.整型.讲讲Python普通整型和长整型的区别. Python的标准整形类型是最通用的数字类型. ...

  10. linux查看日志文件内容命令(面试被常问到的问题)

    tail -f test.log 你会看到屏幕不断有内容被打印出来. 这时候中断第一个进程Ctrl-C, linux 如何显示一个文件的某几行(中间几行) 从第3000行开始,显示1000行.即显示3 ...