游戏编程精粹学习 - 使用Bloom过滤来提高计算性能(BloomFilter)
原文在《游戏编程精粹2》的1.2中,BloomFilter是一种可以快速检测是否存在集合包含关系的数据结构,但有一定的误识别率。
该结构的优点
- 判断包含关系时效率较高,粗略测试了下比List快一倍(不拆分哈希)
- 由于内部是位数组BitArray,做交集并集几乎不产生开销
该结构的缺点
- 有一定的误识别率
- 使用情境有限
我在Github找了一个BloomFilter的库(这个库使用时会产生大量GC,但学习来用够了):
https://github.com/joeyrobert/bloomfilter
首先构建一个长度为N的位数组,将传入数据的哈希值按位拆分成不同段,每一个段作为一个Key放入这个长度为N的位数组。
判断包含时再把对象的多个key与位数组进行比较即可。
当然既然都存在误判率,而且是以效率为优先的话,也可以不按位拆分哈希,我写了一个最简单的版本:
public class MyBloomFilter<T>
{
BitArray mBitArray; public MyBloomFilter(int bitLength)
{
mBitArray = new BitArray(bitLength);
} public void Add(T obj)
{
var key = Mathf.Abs(obj.GetHashCode()) % mBitArray.Length; mBitArray[key] = true;
} public bool Contains(T obj)
{
var key = Mathf.Abs(obj.GetHashCode()) % mBitArray.Length;
return mBitArray[key];
}
}
注意C#已经内置了位数组这样的数据结构BitArray。
结合之前的可预测随机数(http://www.cnblogs.com/hont/p/8716586.html),我写了这样一个例子
假设这是一个草药采集的功能,每一个不同颜色的方块代表一颗草药
鼠标点击来采集它们。
代码如下
using System.Collections.Generic;
using UnityEngine; public class HerbGenerator : MonoBehaviour
{
public int x;
public int y;
public int probability = ;
List<HerbObject> mCreatedHerbList = new List<HerbObject>();
MyBloomFilter<int> mCollectedHerbList = new MyBloomFilter<int>(); void Update()
{
GetArea(x - , y - , x + , y + ); if (Input.GetMouseButtonDown())
{
var hit = default(RaycastHit);
var isHit = Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit);
if (isHit)
{
var herbObject = hit.transform.GetComponent<HerbObject>();
mCollectedHerbList.Add(herbObject.seed); Destroy(hit.transform.gameObject);
}
}
} void GetArea(int beginX, int beginY, int endX, int endY)
{
for (int i = ; i < mCreatedHerbList.Count; i++)
{
if (!mCreatedHerbList[i]) continue;
Destroy(mCreatedHerbList[i].gameObject);
} var cacheState = Random.state; mCreatedHerbList.Clear(); float spacingScale = 1f;//增加间距防止两颗草药同时消失.
for (int x = beginX, k = ; x < endX; x++)
{
for (int y = beginY; y < endY; y++, k++)
{
var seed = + x + y * (endX - beginX); if (mCollectedHerbList.Contains(seed)) continue; Random.InitState(seed);
var r = (int)(Random.value * ); if (r % < probability)
{
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
var herbObject = cube.AddComponent<HerbObject>();
herbObject.seed = seed; cube.transform.position = new Vector3(x * spacingScale, , y * spacingScale); GalaxyBuild(r, cube); mCreatedHerbList.Add(herbObject);
}
}
} Random.state = cacheState;
} void GalaxyBuild(int seed, GameObject go)
{
var cacheState = Random.state;
Random.InitState(seed);
var meshRenderer = go.GetComponent<MeshRenderer>();
switch ((int)(Random.value * % ))
{
case ://草药类型1
meshRenderer.material.color = Color.red;
break; case ://草药类型2
meshRenderer.material.color = Color.blue;
break; case ://草药类型3
meshRenderer.material.color = Color.green;
break;
} Random.state = cacheState;
}
}
HerbGenerator
出现误判时会发生A草药采完后B草药同时消失的情况,只能增加草药刷新的间距来缓解这个问题。
游戏编程精粹学习 - 使用Bloom过滤来提高计算性能(BloomFilter)的更多相关文章
- C++游戏编程(一开篇)
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7318264 作者:毛星云 邮箱: h ...
- c++游戏编程书籍
如果要自学游戏程序开发的话,可以看看下面的,呵呵. 游戏开发资料(PDF书都是中文版的,非英文,很多是本人自己扫描制作,从未网上发布过,所以独家啦): 1.Gamebryo 2.2游戏引擎(盛大.腾 ...
- DirectX 11游戏编程学习笔记之8: 第6章Drawing in Direct3D(在Direct3D中绘制)(习题解答)
本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com 注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...
- 工作流程,编程,调试,性能:Unity游戏开发者应该学习的20个改进技巧
Unity 是一个备受欢迎的游戏开发平台.它的功能令人印象深刻,同时也迎合了不同的游戏开发需求.游戏开发者可以使用 Unity 创建任何类型的游戏,从世界级的 RPG 游戏到最流行的增强现实游戏 Po ...
- 【Visual C++】游戏编程学习笔记之五:单一背景滚动
本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44224963 作者:ZeeCod ...
- 【Visual C++】游戏编程学习笔记之四:透明动画实现
本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44224963 作者:ZeeCod ...
- 【Visual C++】游戏编程学习笔记之三:游戏循环的使用
本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44208419 作者:Zee ...
- 【Visual C++】游戏编程学习笔记之八:鼠标输入消息(小demo)
本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder 微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...
- 【Visual C++】游戏编程学习笔记之七:键盘输入消息
本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder 微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...
随机推荐
- 【noip模拟赛4】Matrix67的派对 dfs
描述 Matrix67发现身高接近的人似乎更合得来.Matrix67举办的派对共有N(1<=N<=10)个人参加,Matrix67需要把他们安排在圆桌上.Matrix67的安排原则是,圆桌 ...
- Minimum Transport Cost HDU1385(路径打印)
最短路的路径打印问题 同时路径要是最小字典序 字典序用floyd方便很多 学会了两种打印路径的方法!!! #include <stdio.h> #include <string.h& ...
- Linux 之 AT&T汇编语言 mov、add、sub指令、数据段
mov指令的几种形式: mov 寄存器. 数据 mov ax,8888 mov 寄存器. 寄存器 mov bx,ax mov 寄存器. 内存单元 mov ax,[0] mov 内存单元.寄存器 mov ...
- ubuntu 18图形界面
sh .start_mode.sh: 换操作方式(图形界面,终端界面): 桌面版: 界面中 ctrl + shift + t 打开终端 ctrl + shift + "+" 放大字 ...
- 简述synchronized和java.util.concurrent.locks.Lock的异同?
主要相同点:Lock能完成synchronized所实现的所有功能 . 主要不同点:Lock有比synchronized更精确的线程语义和更好的性能.synchronized会自动释放锁,而Lock一 ...
- BZOJ.1935.[SHOI2007]Tree园丁的烦恼(CDQ分治 三维偏序)
题目链接 矩形查询可以拆成四个点的前缀和查询(树套树显然 但是空间不够) 每个操作表示为(t,x,y),t默认有序,对x分治,y用树状数组维护 初始赋值需要靠修改操作实现. //119964kb 43 ...
- SPOJ.Visible Lattice Points(莫比乌斯反演)
题目链接 /* http://www.spoj.com/problems/VLATTICE/ 题意:求一个n*n*n的晶体,有多少点可以在(0,0,0)处可以直接看到. 同BZOJ.2301 题目即要 ...
- [HihoCoder1378]网络流二·最大流最小割定理
思路: 根据最大流最小割定理可得最大流与最小割相等,所以可以先跑一遍EdmondsKarp算法.接下来要求的是经过最小割切割后的图中$S$所属的点集.本来的思路是用并查集处理所有前向边构成的残量网络, ...
- 老菜鸟学习:Javascript 将html转成pdf
起因:处理某个项目,需要把页面上的数据(订单.运单)等导出pdf. 第一个想法:从 Java 层去想.但是经过各种资料查询和实践,第一个想法宣告放弃: 幸好客户的要求是:导出的 pdf 尺寸要和打印的 ...
- Shell Step by Step (4) —— Cron & Echo
6.脚本定时任务 # Example of job definition: # .------------------------- minute (0 - 59) # | .------------ ...