^_^内容原创,禁止转载


 假设配置如下:

  1. local reward_pool = {
  2. {weight = , item = {, num = }},
  3. {weight = , item = {, num = }},
  4. {weight = , item = {, num = }},
  5. {weight = , item = {, num = }},
  6. {weight = , item = {, num = }},
  7. {weight = , item = {, num = }},
  8. }

1.顺序查找,预处理时间复杂度O(n),抽奖最坏情况O(n)

  1. --预处理
  2. local N = #reward_pool
  3.  
  4. for _, v in ipairs(reward_pool) do
  5. total_weight = total_weight + v.weight
  6. end
  7.  
  8. --实现
  9. local rand_weight = math.random(total_weight)
  10. local reward_index
  11.  
  12. for k, v in ipairs(reward_pool) do
  13. _total_weight = _total_weight + v.weight
  14. if _total_weight >= rand_weight then
  15. reward_index = k
  16. break
  17. end
  18. end

2.按照离散思路进行分割,二分查找,预处理时间复杂度O(n),抽奖最坏情况O(logn)

  1. --预处理
  2. local N = #reward_pool
  3.  
  4. for _, v in ipairs(reward_pool) do
  5. com_weight = com_weight + v.weight
  6. v.weight = com_weight
  7. end
  8.  
  9. --实现
  10. , #reward_pool
  11. while right >= left then
  12. )
  13. local mid_weight = reward_pool[mid].weight
  14. if value == mid_weight then
  15. right = right -
  16. break
  17. elseif value < mid_weight then
  18. right = mid -
  19. else
  20. left = mid +
  21. end
  22. end
  23. right = right + --此时rightreward_pool中抽到的索引

这种方法在实际上是对第一种方法的优化,在大多数情况下都可以取代第一种方法,但取舍还要看实际情况,一个极端且明显的例子如下:

  1. local reward_pool = {
  2. {weight = , item = {, num = }}, {weight = , item = {, num = }},
  3. {weight = , item = {, num = }}, {weight = , item = {, num = }},
  4. {weight = , item = {, num = }}, {weight = , item = {, num = }},
  5. {weight = , item = {, num = }}, {weight = , item = {, num = }},
  6. {weight = , item = {, num = }}, {weight = , item = {, num = }},
  7. }

3.AliasMethod,个人实现的预处理O(3n),抽奖时间复杂度O(1),下面是实现过程,证明日后有时间再整理给出

  1. queue = {}
  2.  
  3. function queue:new()
  4. , last = -}
  5. self.__index = self
  6. setmetatable(res, self)
  7. return res
  8. end
  9.  
  10. function queue:push(value)
  11. self.last = self.last +
  12. self[self.last] = value
  13. end
  14.  
  15. function queue:pop()
  16. local first = self.first
  17. if first > self.last then
  18. self.first =
  19. self.last = -
  20. return nil
  21. end
  22. local value = self[first]
  23. self[first] = nil
  24. self.first = self.first +
  25. return value
  26. end
  27.  
  28. function queue:front()
  29. return self[self.first]
  30. end
  31.  
  32. --预处理
  33. local N = #reward_pool
  34.  
  35. for _, v in ipairs(reward_pool) do
  36. total_weight = total_weight + v.weight
  37. end
  38.  
  39. local Prob = {}
  40. local Alias = {}
  41. local weightN_queue_L = queue:new()
  42. local weightN_queue_U = queue:new()
  43. for k, v in ipairs(reward_pool) do
  44. local weight_N = v.weight * N
  45. if weight_N == total_weight then
  46. Prob[k] = weight_N
  47. else
  48. local tb = {index = k, value = weight_N}
  49. local qu = weight_N > total_weight and weightN_queue_U or weightN_queue_L
  50. qu:push(tb)
  51. end
  52. end
  53.  
  54. while true do
  55. local l_qu = weightN_queue_L:pop()
  56. if not l_qu then
  57. break
  58. end
  59. local u_qu = weightN_queue_U:front() --或直接pop,比total_weight大再push回去
  60. Prob[l_qu.index] = l_qu.value
  61. Alias[l_qu.index] = u_qu.index
  62. u_qu.value = u_qu.value + l_qu.value - total_weight
  63. if u_qu.value < total_weight then
  64. weightN_queue_U:pop()
  65. weightN_queue_L:push(u_qu)
  66. elseif u_qu.value == total_weight then
  67. weightN_queue_U:pop()
  68. Prob[u_qu.index] = total_weight
  69. end
  70. end
  71. weightN_queue_U = nil
  72. weightN_queue_L = nil
  73.  
  74. --实现
  75. local n = math.random(N)
  76. local weight = math.random(total_weight)
  77. local reward_index = weight > Prob[n] and Alias[n] or n

lua实现游戏抽奖的几种方法的更多相关文章

  1. 【转载】解决繁体、日文游戏乱码的五种方法 转载自:http://tieba.baidu.com/p/488627981

    方法1:转换区域 开始——设置——控制面板——区域和语言选项——分别选择“高级”和“区域选项”标签——在其下拉框中都选择“日语”(或“日本”)(选项有点多,慢慢找)——重启后即可生效. *某影注:日语 ...

  2. Unity3d获取游戏对象的几种方法

    1.GameObject.Find() 通过场景里面的名子或者一个路径直接获取游戏对象. GameObject root = GameObject.Find("GameObject" ...

  3. 游戏对象消失三种方法的区别?(enabled/Destroy/active)

    gameObject.renderer.enabled=fasle是控制一个物体是否在屏幕上渲染或显示  而物体实际还是存在的 只是想当于隐身 而物体本身的碰撞体还依然存在的GameObject.De ...

  4. slua中,绑定lua文件到Monobehavior的一种方法

    slua本身并不提供如何把一个lua文件绑定到一个预制中,就像一个普通的继承自monobehavior的自定义脚本那样,而tolua的框架却采用了拙劣的做法: public class LuaBeha ...

  5. unity3d 游戏对象消失三种方法的区别(enabled/Destroy/active)

    gameObject.renderer.enabled //是控制一个物体是否在屏幕上渲染或显示 而物体实际还是存在的 只是想当于隐身 而物体本身的碰撞体还依然存在的 GameObject.Destr ...

  6. 【Cocos2d-x游戏开发】解决Cocos2d-x中文乱码的三种方法

    众所周知,Cocos2d-x是一款不错的开源引擎,但是在Cocos2d-x中直接使用中文是无法正确显示的.比如下面的情况: 解决这个问题常用的有三种方法:1.通过转换为UTF-8编码来显示.2.使用i ...

  7. C模块回调Lua函数的两种方法

    作者:ani_di 版权所有,转载务必保留此链接 http://blog.csdn.net/ani_di C模块回调Lua函数的两种方法 lua和C通过虚拟栈这种交互方式简单而又可靠,缺点就是C做栈平 ...

  8. [Unity3D]Unity3D游戏开发Lua随着游戏的债券(于)

    ---------------------------------------------------------------------------------------------------- ...

  9. lua中 table 重构index/pairs元方法优化table内存占用

    转载请标明出处http://www.cnblogs.com/zblade/ lua作为游戏的热更新首选的脚本,其优势不再过多的赘述.今天,我主要写一下如何重写lua中的元方法,通过自己的重写来实现对l ...

随机推荐

  1. js 的 new 干了什么

  2. SubLime Text3 常用插件总结

    近来开始恶补前端知识,在一定的技能基础上,逐渐开始进阶的学习和使用.因此在这里罗列下,SubLime Text3 常用插件: 1.Emmet 提高HTML & CSS3编写速度. 2.Them ...

  3. elasticsearch报Fielddata is disabled on text fields by default

    我刚玩elk没几天,今天启动kibana之后执行查询看见elasticsearch报了一个错误 Caused by: java.lang.IllegalArgumentException: Field ...

  4. Git之旅

    ithub安装,我选择的是windows下的版本. git配置用户信息 安装完成后,还需要最后一步设置,在命令行输入: $git config --global user.name "You ...

  5. docker 搭建keepalived+nginx高可用

    前言 最近工作 中 有用到keepalived,就想着 在 本地 搭建一套环境验证一下相关的功能.因为创建虚拟机比较麻烦,就借助  docker来搭建这样 一套 环境 ,顺带学习 巩固下docker的 ...

  6. 一分钟 Get 时序数据库 InfluxDB 的技能

    1. 通过上期分享<实践指路明灯,源码剖析flink-metrics>,对当下较火的流式处理框架 flink 的指标监控体系有了全局的认识,并结合 flink-metrics-xxxx 模 ...

  7. SaaS架构(一) 弱后端强前端的尝试和问题

    最近在公司项目组内部沙龙的时候,提出一个"弱后端强前端"的概念,其实已经在项目内部新的服务有做试点,我们整个SaaS系统,后端主要是JAVA构建,前端是Angular构建.&quo ...

  8. Integer类的进制之间转换的方法

    一.两个通用方法 1.public static String toString(int i,int radix) (1)作用 将十进制的数转化成指定进制数的字符串形式:radix参数指进制数: (2 ...

  9. jQuery实现回车键抬起触发事件

    $(function(){ //回车键按下触发 $(document).keydown(function(event){ if(event.keyCode==13){ alert("niha ...

  10. Mysql数据库卸载

    Mysql数据库卸载的操作流程(Windows10): 1.停止mysql的所有服务 方法一:此电脑——管理——服务中查找到所有Mysql的服务,并停止. 方法二:cmd——net stop mysq ...