lua实现游戏抽奖的几种方法
^_^内容原创,禁止转载
假设配置如下:
- local reward_pool = {
- {weight = , item = {, num = }},
- {weight = , item = {, num = }},
- {weight = , item = {, num = }},
- {weight = , item = {, num = }},
- {weight = , item = {, num = }},
- {weight = , item = {, num = }},
- }
1.顺序查找,预处理时间复杂度O(n),抽奖最坏情况O(n)
- --预处理
- local N = #reward_pool
- for _, v in ipairs(reward_pool) do
- total_weight = total_weight + v.weight
- end
- --实现
- local rand_weight = math.random(total_weight)
- local reward_index
- for k, v in ipairs(reward_pool) do
- _total_weight = _total_weight + v.weight
- if _total_weight >= rand_weight then
- reward_index = k
- break
- end
- end
2.按照离散思路进行分割,二分查找,预处理时间复杂度O(n),抽奖最坏情况O(logn)
- --预处理
- local N = #reward_pool
- for _, v in ipairs(reward_pool) do
- com_weight = com_weight + v.weight
- v.weight = com_weight
- end
- --实现
- , #reward_pool
- while right >= left then
- )
- local mid_weight = reward_pool[mid].weight
- if value == mid_weight then
- right = right -
- break
- elseif value < mid_weight then
- right = mid -
- else
- left = mid +
- end
- end
- right = right + --此时right为reward_pool中抽到的索引
这种方法在实际上是对第一种方法的优化,在大多数情况下都可以取代第一种方法,但取舍还要看实际情况,一个极端且明显的例子如下:
- local reward_pool = {
- {weight = , item = {, num = }}, {weight = , item = {, num = }},
- {weight = , item = {, num = }}, {weight = , item = {, num = }},
- {weight = , item = {, num = }}, {weight = , item = {, num = }},
- {weight = , item = {, num = }}, {weight = , item = {, num = }},
- {weight = , item = {, num = }}, {weight = , item = {, num = }},
- }
3.AliasMethod,个人实现的预处理O(3n),抽奖时间复杂度O(1),下面是实现过程,证明日后有时间再整理给出
- queue = {}
- function queue:new()
- , last = -}
- self.__index = self
- setmetatable(res, self)
- return res
- end
- function queue:push(value)
- self.last = self.last +
- self[self.last] = value
- end
- function queue:pop()
- local first = self.first
- if first > self.last then
- self.first =
- self.last = -
- return nil
- end
- local value = self[first]
- self[first] = nil
- self.first = self.first +
- return value
- end
- function queue:front()
- return self[self.first]
- end
- --预处理
- local N = #reward_pool
- for _, v in ipairs(reward_pool) do
- total_weight = total_weight + v.weight
- end
- local Prob = {}
- local Alias = {}
- local weightN_queue_L = queue:new()
- local weightN_queue_U = queue:new()
- for k, v in ipairs(reward_pool) do
- local weight_N = v.weight * N
- if weight_N == total_weight then
- Prob[k] = weight_N
- else
- local tb = {index = k, value = weight_N}
- local qu = weight_N > total_weight and weightN_queue_U or weightN_queue_L
- qu:push(tb)
- end
- end
- while true do
- local l_qu = weightN_queue_L:pop()
- if not l_qu then
- break
- end
- local u_qu = weightN_queue_U:front() --或直接pop,比total_weight大再push回去
- Prob[l_qu.index] = l_qu.value
- Alias[l_qu.index] = u_qu.index
- u_qu.value = u_qu.value + l_qu.value - total_weight
- if u_qu.value < total_weight then
- weightN_queue_U:pop()
- weightN_queue_L:push(u_qu)
- elseif u_qu.value == total_weight then
- weightN_queue_U:pop()
- Prob[u_qu.index] = total_weight
- end
- end
- weightN_queue_U = nil
- weightN_queue_L = nil
- --实现
- local n = math.random(N)
- local weight = math.random(total_weight)
- local reward_index = weight > Prob[n] and Alias[n] or n
lua实现游戏抽奖的几种方法的更多相关文章
- 【转载】解决繁体、日文游戏乱码的五种方法 转载自:http://tieba.baidu.com/p/488627981
方法1:转换区域 开始——设置——控制面板——区域和语言选项——分别选择“高级”和“区域选项”标签——在其下拉框中都选择“日语”(或“日本”)(选项有点多,慢慢找)——重启后即可生效. *某影注:日语 ...
- Unity3d获取游戏对象的几种方法
1.GameObject.Find() 通过场景里面的名子或者一个路径直接获取游戏对象. GameObject root = GameObject.Find("GameObject" ...
- 游戏对象消失三种方法的区别?(enabled/Destroy/active)
gameObject.renderer.enabled=fasle是控制一个物体是否在屏幕上渲染或显示 而物体实际还是存在的 只是想当于隐身 而物体本身的碰撞体还依然存在的GameObject.De ...
- slua中,绑定lua文件到Monobehavior的一种方法
slua本身并不提供如何把一个lua文件绑定到一个预制中,就像一个普通的继承自monobehavior的自定义脚本那样,而tolua的框架却采用了拙劣的做法: public class LuaBeha ...
- unity3d 游戏对象消失三种方法的区别(enabled/Destroy/active)
gameObject.renderer.enabled //是控制一个物体是否在屏幕上渲染或显示 而物体实际还是存在的 只是想当于隐身 而物体本身的碰撞体还依然存在的 GameObject.Destr ...
- 【Cocos2d-x游戏开发】解决Cocos2d-x中文乱码的三种方法
众所周知,Cocos2d-x是一款不错的开源引擎,但是在Cocos2d-x中直接使用中文是无法正确显示的.比如下面的情况: 解决这个问题常用的有三种方法:1.通过转换为UTF-8编码来显示.2.使用i ...
- C模块回调Lua函数的两种方法
作者:ani_di 版权所有,转载务必保留此链接 http://blog.csdn.net/ani_di C模块回调Lua函数的两种方法 lua和C通过虚拟栈这种交互方式简单而又可靠,缺点就是C做栈平 ...
- [Unity3D]Unity3D游戏开发Lua随着游戏的债券(于)
---------------------------------------------------------------------------------------------------- ...
- lua中 table 重构index/pairs元方法优化table内存占用
转载请标明出处http://www.cnblogs.com/zblade/ lua作为游戏的热更新首选的脚本,其优势不再过多的赘述.今天,我主要写一下如何重写lua中的元方法,通过自己的重写来实现对l ...
随机推荐
- js 的 new 干了什么
- SubLime Text3 常用插件总结
近来开始恶补前端知识,在一定的技能基础上,逐渐开始进阶的学习和使用.因此在这里罗列下,SubLime Text3 常用插件: 1.Emmet 提高HTML & CSS3编写速度. 2.Them ...
- elasticsearch报Fielddata is disabled on text fields by default
我刚玩elk没几天,今天启动kibana之后执行查询看见elasticsearch报了一个错误 Caused by: java.lang.IllegalArgumentException: Field ...
- Git之旅
ithub安装,我选择的是windows下的版本. git配置用户信息 安装完成后,还需要最后一步设置,在命令行输入: $git config --global user.name "You ...
- docker 搭建keepalived+nginx高可用
前言 最近工作 中 有用到keepalived,就想着 在 本地 搭建一套环境验证一下相关的功能.因为创建虚拟机比较麻烦,就借助 docker来搭建这样 一套 环境 ,顺带学习 巩固下docker的 ...
- 一分钟 Get 时序数据库 InfluxDB 的技能
1. 通过上期分享<实践指路明灯,源码剖析flink-metrics>,对当下较火的流式处理框架 flink 的指标监控体系有了全局的认识,并结合 flink-metrics-xxxx 模 ...
- SaaS架构(一) 弱后端强前端的尝试和问题
最近在公司项目组内部沙龙的时候,提出一个"弱后端强前端"的概念,其实已经在项目内部新的服务有做试点,我们整个SaaS系统,后端主要是JAVA构建,前端是Angular构建.&quo ...
- Integer类的进制之间转换的方法
一.两个通用方法 1.public static String toString(int i,int radix) (1)作用 将十进制的数转化成指定进制数的字符串形式:radix参数指进制数: (2 ...
- jQuery实现回车键抬起触发事件
$(function(){ //回车键按下触发 $(document).keydown(function(event){ if(event.keyCode==13){ alert("niha ...
- Mysql数据库卸载
Mysql数据库卸载的操作流程(Windows10): 1.停止mysql的所有服务 方法一:此电脑——管理——服务中查找到所有Mysql的服务,并停止. 方法二:cmd——net stop mysq ...