瓜分游戏币,红包拆分正态分布

阅读: 评论:0

瓜分游戏币,红包拆分正态分布

瓜分游戏币,红包拆分正态分布

背景

需要做一个给每个人参加活动的人瓜分固定奖池的游戏币,有平均瓜分和随机分2种分配方案。

平均瓜分

平均分很简单,就是总money/总person取整数就行,无论整除不整除,不整除有结余也无所谓。

随机瓜分

需求详情

根据一个时间段的参与人数设置一个总游戏币数,所有人进行瓜分,每个人最少获得一个币,同时可以无限次重新随机计算,计算出来的列表进行分页展示,而且支持对单个人获得币进行修改,然后统一生成奖励。

思路

  1. 可以多次进行重新随机计算,所以不能直接将计算的结果持久化,防止大量操作删表新增操作,所以先保存数据到redis中做缓存
  2. 在缓存中需要做分页查询,类似查询榜单,list,zset类型可实现分页查询,不需要每次查询都将所有数据拉出来进行分页筛选,zset占用空间大,而且也不需要格外的value做实时排列。所以暂时选用list做存储类型
  3. 缓存中需要保存用户与随机得到的游戏币的对应,选用person+分隔符+币 的String拼接实现
  4. 需要针对一个用户获得币进行修改,list类型可根据下标索引进行修改,可支持
  5. 计算出来后,每个用户对应一个随机游戏币,需要按币的大小进行排序,存入redis,重写list,String排序实现

代码实现

涉及的redis操作(简化)

jedis.lpush(key,value); //存放key,value value是可变类型,LPUSH mylist a b c
jedis.lrange(key, startNumber, endNumber);//查询
jedis.lset(key,index,value); //根据index进行修改
jedis.lindex(key, index); //根据当前index获取list中的值
随机算法工具类
  1. 模拟微信红包算法(简单实现)
    1. 每个人最少得到1游戏币,所以先给每个人分配一个游戏币,保证在随机下每个人所得不为0

    2. 随机每个人所得范围在(0-money / people * 2)

    3. 同时利用Random产生的随机数固定种子下产生的随机序列数相同来排查记录。

    4. 当前利用微信抢红包不需要一次性将整个分布计算下来,可以在每个人领红包的时候再进行计算

    5. 利用excel工具直观查看随机数分布是否满足预想

    6. 废话不多说,贴代码:

@Testpublic void randTestTest(){randTest(1000,100);}public static void randTest(int sum,int count){List<Integer> list = new ArrayList<>();sum = sum-count*1;Random random = new Random();long factor = System.currentTimeMillis();System.out.println("固定种子是:"+factor);random.setSeed(factor);//当random设置相同的种子时,随机序列数相同for(int i = 0;i<count;i++){int rand = rand(sum, count-i, list,random);sum = rand;}int summoneny = 0;int min &#(0);int max =-1;for(Integer entry :list){summoneny = summoneny+entry.intValue();min = Math.min(min,entry.intValue());max = Math.max(max,entry.intValue());}System.out.String());System.out.println(min);System.out.println(max);}/**** @param money 剩余的钱* @param people 剩余的人数* @param l   红包列表* @return*/public static int rand(int money, int people, List<Integer> l ,Random random) {if (people == 1) {int red = money;l.add(red+1);return 0;}int min = 0;int max = money / people * 2;int red = Int(max);red = red <= min ? min : red;l.add(red+1);int remain = money-red;return remain;}
  1. 以上思想是每个人口袋能得到多少游戏币,随机在奖池中取钱。现我们转变一下思想,利用游戏币找口袋,游戏币随机落入口袋。
    1. 分布图展示,看起来后者分布更加均匀

    2. 利用钱找人,有可能一个人没有被找过一次,当然可以先给每个人先分一个游戏币,然后剩下的币找人,上代码

 @Testpublic void rand1Test(){Random random = new Random();long factor = System.currentTimeMillis();System.out.println("固定种子是:"+factor);random.setSeed(factor);//当random设置相同的种子时,随机序列数相同int[] ints = rand1(1000, 100, random);int a = 0;int min =ints[0];int max =-1;for (int integer : ints) {a+=integer;min = Math.min(min,integer);max = Math.max(max,integer);}System.out.String(ints));System.out.println(a);System.out.println(min);System.out.println(max);}/**** @param money 总钱* @param count 剩余的人数* @return*/public int[] rand1(int money, int count ,Random random) {int[] nums = new int[count];for(int i= 0;i<money;i++){int person = Int(count);nums[person] +=1;}return nums;}
重写排序工具类
 public static void sortListString(List list){System.out.println("排序前:"&#String());Collections.sort(list, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return Integer.valueOf(o1.substring(o1.indexOf(":")+1,o1.length()))pareTo(Integer.valueOf((o2.substring(o2.indexOf(":")+1,o2.length()))));}});System.out.println("排序后:"&#String());}

总结

  1. 整个过程也看过网上很多介绍正态分布的算法,还有网上各位大神的分析与实现,以上是一个简单的实现同时也很好的契合要求,故实现如此,作此记录。
  2. 在redis的操作文档中只发现如下的存储方式,RPUSH mylist a b c,所以选择String作为载体进行存储,当然可以选择list中保存可序列化对象,将对象序列化后再保存到redis中,可以添加更多的属性。由于时间问题并未依此方案实现。

本文发布于:2024-01-29 04:17:18,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170647304112636.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:正态分布   红包   游戏币
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23