java实现砸金蛋抽奖功能
本文实例为大家分享了java实现砸金蛋抽奖的具体代码,供大家参考,具体内容如下
代码如下
需求:用户每一次砸金蛋,抽中一等奖的概率为2%二等奖10%三等奖18%四等奖70%。
累计砸第n次时必抽中x等奖以上的奖品。比如,累计砸第5次,则此次必中二等奖及以上的奖品。且配置的此次必中中奖概率不一样。
/** *金蛋抽奖 *userId:抽奖用户ID *consumeType:抽奖消耗的物品1:金币2:次数 */ @Override publicMapeggsLottery(IntegeruserId,IntegerconsumeType){ /*******first:checkuser************/ checkUserIsLock(userId); logger.info("userId{}startlottery-eggs.",userId); Jedisjedis=RedisPool.getJedis(); try{ //查询活动开关 Stringhget=jedis.hget(Rkey.SMASH_GOLD_EGGS_GLOBAL_CONFIG,"status"); if(null==hget||"0".equals(hget)){ thrownewBusiException(E.INVALID_PARAMETER,"活动暂未开启,敬请期待"); } //checklotterytype LongconsumeScore=0L; /**scorelottery**/ consumeScore=jedis.hincrBy(Rkey.SMASH_GOLD_EGGS_GLOBAL_CONFIG,"consumeGoldScore",0); if(consumeScore<1){ thrownewBusiException(E.EGGS_ACTIVITY_CONFIG_EXCEPTION,"活动配置有误!"); } longsurScore=goldWalletMapper.selectAmountGoldByUserId(userId); surScore=surScore-consumeScore; if(surScore<0){ thrownewBusiException(E.SCORE_NOT_ENOUGH,"您的金币不足"); } //砸金蛋之前扣除金币 Datenow=newDate(); reduceGold(consumeScore,now,userId); /*******second:lottery************/ Map map; try{ map=lottery(jedis,now,userId,consumeScore); //抽奖结束后记录今日总共完成的抽奖次数+1 //必中不加 jedis.hincrBy(Rkey.SMASH_GOLD_EGGS_USER_WIN_TOTAL_COUNT,userId.toString(),1); }catch(Exceptione){ throwe; } returnmap; }finally{ RedisPool.returnJedis(jedis); } } /** *抽奖begin---- */ privateMap lottery(Jedisjedis,Datenow,IntegeruserId,LongconsumeScore){ Map map=newHashMap (); //判断本次是否是必中?jackpotType=1:不是2:是必中 IntegerjackpotType=1; //剩余次数 IntegerfreeCount=0; StringcountStr=jedis.hget(Rkey.SMASH_GOLD_EGGS_USER_WIN_COUNT,userId.toString()); if(StringUtils.isNotEmpty(countStr)){ Integercount=Integer.valueOf(countStr); StringwhenAwardCount=jedis.hget(Rkey.SMASH_GOLD_EGGS_GLOBAL_CONFIG,"whenAwardCount"); if(StringUtils.isEmpty(whenAwardCount)){ thrownewBusiException(E.INVALID_REQUEST,"请先完善砸金蛋全局配置"); } freeCount=Integer.valueOf(whenAwardCount)-count-1; if(count>=Integer.valueOf(whenAwardCount)-1){ logger.info("此次是必中...."); //此次是必中 jackpotType=2; //抽奖结束后先把记录总共完成的抽奖次数置为0次 jedis.hdel(Rkey.SMASH_GOLD_EGGS_USER_WIN_COUNT,userId.toString()); jedis.hincrBy(Rkey.SMASH_GOLD_EGGS_USER_WIN_COUNT,userId.toString(),0); }else{ logger.info("此次不是必中...."); } if(freeCount==0){ freeCount=Integer.valueOf(whenAwardCount); } } //根据配置得到总的奖品数量 IntegertotalCount=0; if(jackpotType==1){ totalCount=getAwardTotalCount(1); }else{ totalCount=getAwardTotalCount(2); } Integeraward=getRandomNumber(totalCount); //看落在哪个区间 IntegerawardId=getWinAwardId(award,jackpotType); BsGoldEggsConfiggoldEggsConfig=goldEggsConfigMapper.selectById(awardId); if(goldEggsConfig==null){ thrownewBusiException(E.INVALID_REQUEST,"奖品信息未找到"); } map.put("freeCount",freeCount); map.put("userId",userId); map.put("awardId",awardId); map.put("awardName",goldEggsConfig.getDescribe()); map.put("goldCount",goldEggsConfig.getGoldCount()); map.put("awardImg",goldEggsConfig.getAwardImg()); logger.info("userId{}winaward{},奖励金币:{},随机生成抽奖数:{}",userId,goldEggsConfig.getDescribe(),goldEggsConfig.getGoldCount(),award); //抽奖结束action: if(jackpotType==1){ //抽奖结束后记录累计抽奖次数+1 //必中不加 jedis.hincrBy(Rkey.SMASH_GOLD_EGGS_USER_WIN_COUNT,userId.toString(),1); } //奖励金币结算 Datenow1=newDate(); lotteryAddGold(goldEggsConfig.getGoldCount().longValue(),now1,userId); returnmap; } /** *得到中奖id * *@paramaward:随机生成的抽奖数字 *@return */ privateIntegergetWinAwardId(Integeraward,IntegerjackpotType){ List goldEggsConfigList=goldEggsConfigMapper.queryAllList(); if(goldEggsConfigList==null||goldEggsConfigList.size()<4){ thrownewBusiException(E.INVALID_REQUEST,"请先完成砸金蛋奖品配置!"); } Integer[]weight=newInteger[4]; if(jackpotType==1){ //基础抽奖 for(inti=0;i 下面是用奖池写的一个算法读者可忽略,博主只是记录一下。
思路:
根据需求:
1.生成两类奖池(普通奖池,和必中奖池),中奖概率不一样!为了保证概率正确,我们生成100组(1-100)的数字,随机打乱放入redis中,作为一个奖池。
2.生成中奖区间,放入redis
3.每次用户砸金蛋,从奖池里面取一个数,
4.判断该数在哪个中奖区间
/** *抽奖begin----该方法废除 */ privateMaplottery2(Jedisjedis,Datenow,IntegeruserId,LongconsumeScore){ //从奖池中拿出第一个奖品 StringjackpotKey=Rkey.SMASH_GOLD_EGGS_JACKPOT_+"one"; StringbaseWinLimitKey=Rkey.SMASH_GOLD_EGGS_AWARD_WIN_LIMIT_BASE; StringnextWinLimitKey=Rkey.SMASH_GOLD_EGGS_AWARD_WIN_LIMIT_NEXT; Map map=newHashMap (); //奖池存在且奖池不为空 StringawardFlag=jedis.lpop(jackpotKey);//如:20 Integeraward=Integer.valueOf(awardFlag); // if(!StringUtils.isEmpty(awardFlag)){ //判断该奖品的等级 //这里是有问题的博主后面纠正 Set winLimitSet=jedis.zrange(baseWinLimitKey,0,award-1); if(winLimitSet!=null&&!winLimitSet.isEmpty()){ Integersize=winLimitSet.size(); Listlist=newArrayList(winLimitSet); //取区间最后一个 StringlastAwardLevel=String.valueOf(list.get(size-1)); //获取奖品info Integerid=null; if("one".equals(lastAwardLevel)){ id=1; }elseif("two".equals(lastAwardLevel)){ id=2; }elseif("three".equals(lastAwardLevel)){ id=3; }elseif("four".equals(lastAwardLevel)){ id=4; } BsGoldEggsConfiggoldEggsConfig=goldEggsConfigMapper.selectById(id); if(goldEggsConfig==null){ thrownewBusiException(E.INVALID_REQUEST,"奖品信息未找到"); } map.put("userId",userId); map.put("awardId",id); map.put("awardName",goldEggsConfig.getDescribe()); map.put("goldCount",goldEggsConfig.getGoldCount()); logger.info("userId{}winaward{},奖励金币:{},随机生成抽奖数:{}",userId,goldEggsConfig.getDescribe(),goldEggsConfig.getGoldCount(),award); } } returnmap; } /** *生成奖池 * *@paramjackpotType:奖池类型1:普通奖池2:必中奖池 *@paramjackpotSort:奖池序号1,2,3......如普通奖池1,普通奖池2, */ @Override publicvoidaddAwardToJackpot(IntegerjackpotType,IntegerjackpotSort){ //存放奖池数据 List awadList=newArrayList<>(); //奖池key StringjackpotKey=""; StringjackpotTypeToStr=""; if(jackpotType==1){ jackpotTypeToStr="普通"; jackpotKey=Rkey.SMASH_GOLD_EGGS_JACKPOT_+jackpotSort; }else{ jackpotTypeToStr="必中"; jackpotKey=Rkey.SMASH_GOLD_EGGS_NEXT_WIN_JACKPOT_+jackpotSort; } logger.info("开始生成{}奖池{}。。。。。",jackpotTypeToStr,jackpotSort); Jedisjedis=RedisPool.getJedis(); try{ if(jedis.exists(jackpotKey)){ //判断奖池中是否还有奖品 Longlength=jedis.llen(jackpotKey); if(length<=0){ //奖池空了,重新放入奖品 logger.info("{}奖池{}空了,重新放入奖品。。。。。",jackpotTypeToStr,jackpotSort); //根据配置得到总的奖品数量 IntegertotalCount=getAwardTotalCount(1); setSingleAwardToJackpot(awadList,jedis,jackpotKey,totalCount); } }else{ //直接生成奖池 logger.info("{}奖池{}不存在,直接放入奖品。。。。。",jackpotTypeToStr,jackpotSort); IntegertotalCount=getAwardTotalCount(1); setSingleAwardToJackpot(awadList,jedis,jackpotKey,totalCount); } }finally{ RedisPool.returnJedis(jedis); } } /** *获取奖池奖品数量 * *@paramtype奖池类型:1:普通奖池2:必中奖池 *@return */ IntegergetAwardTotalCount(Integertype){ List goldEggsConfigList=goldEggsConfigMapper.queryAllList(); if(goldEggsConfigList==null||goldEggsConfigList.size()<4){ thrownewBusiException(E.INVALID_REQUEST,"请先完成砸金蛋奖品配置!"); } IntegertotalCount=0; if(type==1){ //普通奖池奖品数量 for(BsGoldEggsConfiggoldEggsConfig:goldEggsConfigList){ totalCount+=goldEggsConfig.getBaseWeight(); } }else{ //必中奖池数量 Jedisjedis=RedisPool.getJedis(); try{ StringmustAwardLevel=jedis.hget(Rkey.SMASH_GOLD_EGGS_GLOBAL_CONFIG,"mustAwardLevel"); if(StringUtils.isEmpty(mustAwardLevel)){ thrownewBusiException(E.INVALID_REQUEST,"请先完成砸金蛋奖品配置!"); } for(inti=0;i awadList,Jedisjedis,StringjackpotKey,IntegertotalCount){ //1.生成100组[1-100]随机数awadList for(inti=0;i<2;i++){ List list=getOneToHundredNumber(totalCount); for(Integerj:list){ awadList.add(j.toString()); } } //2.awadList打乱放入redis(list)这里打乱2次 Collections.shuffle(awadList); Collections.shuffle(awadList); //3.放入redis awadList.forEach(s->jedis.lpush(jackpotKey,s)); logger.info("奖品info:预设值:{}实际设置:{}",10000,awadList.size()); } /** *jdk8得到包含1-end数字的list *end:生成数字的个数 * *@return */ privateList getOneToHundredNumber(Integerend){ //起始数字 intstart=1; //生成数字的个数 //intend=100; //生成1,2,3,4,5...100 List list=Stream.iterate(start,item->item+1).limit(end).collect(Collectors.toList()); returnlist; } 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。