需求简介

新项目有一个类似王者荣耀抽奖的功能:抽取花费积分,积累幸运值,每阶段幸运值可以抽取到不同的奖品,幸运值集满时,必得稀有道具

功能实现预期:建立一个抽奖池(抽奖池级别根据type区分),奖品在不同的抽奖池中,获取用户幸运值,创建一个List,达到要求就将该抽奖池中的奖品放入该抽奖集合中,进行抽奖,如果幸运值为满,则只将特殊道具放入抽奖池中,进行抽奖

第一步:创建数据库相关数据表

抽奖池表:此处原本要建立两张表(抽奖池(如果是两张表lucky_restrict 是可以直接限制奖池条件的,一张表时,该字段废弃),和奖池道具),但是因为项目没啥特殊要求,所以就先凑合用了

CREATE TABLE `t_draw_pool` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`prop_id` int(11) DEFAULT NULL COMMENT '道具ID',

`type` int(1) DEFAULT '1' COMMENT '奖池级别,0号奖池,1号奖池,2号奖池,3稀有奖池',

`lucky_restrict` varchar(255) DEFAULT NULL COMMENT '(废弃)限制条件:奖池抽奖限制幸运值限制',

`probability` int(11) DEFAULT NULL COMMENT '中奖概率,总概率的多少分之一,如果所有道具的概率总和为100 当前奖品的概率是1,那么中奖概率就是百分之一',

`top` int(11) DEFAULT '0' COMMENT '道具排序',

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4

道具表:此表为奖品池中的道具

CREATE TABLE `t_prop` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`name` varchar(255) DEFAULT NULL COMMENT '物品名称',

`description` varchar(512) DEFAULT NULL COMMENT '描述',

`type` int(11) DEFAULT NULL COMMENT '0实体,1虚拟,2价值点',

`status` int(11) DEFAULT NULL COMMENT '物品状态,0正常,1删除',

`num` int(11) DEFAULT NULL COMMENT '物品数量',

`price` double DEFAULT NULL COMMENT '价值点',

`price_type` int(11) DEFAULT NULL COMMENT '2积分',

`url` varchar(1024) DEFAULT NULL COMMENT '道具展示图',

`create_time` datetime DEFAULT NULL COMMENT '物品创建时间',

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4

抽奖套餐表:这张表,原先是用来存放购买积分套餐的,但是因为字段相同,没必要新增一张表,就加个type进行了区分

CREATE TABLE `t_starlight_set_meal` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`ios_id` varchar(255) DEFAULT NULL COMMENT 'IOS内购id',

`price` double DEFAULT NULL COMMENT '价格 金额 | 积分',

`amount` int(11) DEFAULT NULL COMMENT '套餐内积分数量 | 套餐内抽奖次数',

`name` varchar(255) DEFAULT NULL COMMENT '套餐名称',

`description` varchar(255) DEFAULT NULL COMMENT '套餐描述',

`url` varchar(512) DEFAULT NULL COMMENT '积分展示图片',

`top` int(11) DEFAULT NULL COMMENT '套餐排序',

`type` int(1) DEFAULT '0' COMMENT '2抽奖套餐',

`create_time` datetime DEFAULT NULL COMMENT '创建时间',

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='星云币充值套餐'

用户钱包表:存放积分(即抽奖积分)、幸运值等信息,当前项目中,积分不计入账单,所以就没有相对应的账单列表,有需要的可以在每次修改钱包时去记录账单,此处不做赘述

CREATE TABLE `t_wallet` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`user_id` int(11) NOT NULL COMMENT '用户id',

`starlight` int(11) NOT NULL DEFAULT '0' COMMENT '积分',

`lucky` int(11) NOT NULL DEFAULT '0' COMMENT '幸运值',

PRIMARY KEY (`id`),

UNIQUE KEY `idx_userId` (`user_id`)

) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='钱包:积分、幸运值'

用户背包表:背包也是应该建立两张表(背包表:应包含礼物数量限制 和 背包容量,背包物品表:关联背包和物品信息),同是因为没有必须要,就使用一张表代替了

CREATE TABLE `t_knapsack` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`user_id` int(11) NOT NULL COMMENT '用户id',

`gift_id` int(11) NOT NULL COMMENT '道具id | 礼物id',

`numble` int(11) DEFAULT '1' COMMENT '礼物数量,无限制',

`capacity` int(11) DEFAULT '100' COMMENT '(废弃)背包容量,无限制',

`occupying_dosage` int(11) DEFAULT '0' COMMENT '(废弃)背包占用量,无限制',

`type` int(1) DEFAULT '0' COMMENT '0道具背包,1礼物背包',

PRIMARY KEY (`id`),

UNIQUE KEY `IDX_userId` (`user_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='用户背包'

以上相关数据表建立完成,生成相对应的对象即可(DrawPool、Prop、Wallet、Knapsack、StarlightSetMeal)

第二步:代码逻辑

public classDrawPoolService {

@ResourceprivateDrawPoolMapper drawPoolMapper;

@ResourceprivatePropMapper propMapper;

@ResourceprivateWalletMapper walletMapper;

@ResourceprivateKnapsackMapper knapsackMapper;

@ResourceprivateStarlightSetMealMapper starlightSetMealMapper;

/***奖池列表*@return*/publicMap list(Integer currentUserId) {

Map result = newHashMap<>();

List drawPoolList = drawPoolMapper.selectByType(null);

for(DrawPool drawPool : drawPoolList){

drawPool.setPropInfo(propMapper.selectByPrimaryKey(drawPool.getPropId()));

}

//封装奖品信息result.put("prop", drawPoolList);

//封装幸运值上限,暂定500result.put("upperLucky", 500);

//封装用户星云币、积分、幸运值信息if(currentUserId != null){

result.put("walletInfo", walletMapper.selectByUserId(currentUserId));

}else{

result.put("walletInfo", null);

}

List starlightSetMeals = starlightSetMealMapper.selectByType(2);

result.put("starlightSetMeals", starlightSetMeals);

returnresult;

}

/***抽奖*@paramcurrentUserId抽奖用户*@paramstarlightSetMealId抽奖套餐ID*@return*/publicResponseVO luckDraw(intcurrentUserId, intstarlightSetMealId){

Map result = newHashMap<>();

List propList = newArrayList<>();

Wallet wallet = walletMapper.selectByUserId(currentUserId);

StarlightSetMeal starlightSetMeal = starlightSetMealMapper.selectByPrimaryKey(starlightSetMealId);

if(wallet == null|| starlightSetMeal == null){

returnResponseVO.error("不满足抽奖条件");

}

//此次抽奖应该消耗的积分intusrStarlight = starlightSetMeal.getPrice().intValue();

intnum = starlightSetMeal.getAmount();

if(wallet.getStarlight() < usrStarlight){

returnResponseVO.error("积分不足");

}

//更新积分数量, 积分不用记录账单wallet.setStarlight(wallet.getStarlight() - usrStarlight);

walletMapper.updateByPrimaryKeySelective(wallet);

//一号奖池上限intoneUpperLucky = 200;

//二号奖池上限inttowUpperLucky = 300;

booleanisResetLucky = false;

for(inti = 0; i < num; i++){

//更新幸运值wallet = walletMapper.selectByUserId(currentUserId);

//返回抽奖池列表结果List drawPoolList = newArrayList<>();

//根据幸运值获取不同的抽奖池if(wallet.getLucky() >= 0&& wallet.getLucky() < towUpperLucky){

drawPoolList.addAll(drawPoolMapper.selectByType(1));

}

if(wallet.getLucky() >= towUpperLucky && wallet.getLucky() < oneUpperLucky){

drawPoolList.addAll(drawPoolMapper.selectByType(2));

}

if(wallet.getLucky() >= oneUpperLucky){

//如果当前用户的幸运值大于550,必得特殊道具drawPoolList.addAll(drawPoolMapper.selectByType(3));

isResetLucky = true;

}

intprizeId = getPrizeIndex(drawPoolList);

//如果奖品是价值点之类的,直接增加Prop prop = propMapper.selectByPrimaryKey(prizeId);

if(prop.getType() == 2){

wallet.setStarlight(wallet.getStarlight() + prop.getNum());

walletMapper.updateByPrimaryKeySelective(wallet);

}else{

//如果是道具,就存放到用户背包Knapsack knapsack = knapsackMapper.getKnapsack(currentUserId, Constants.Knapsack.Type.PROP, prizeId);

if(ValidateUtils.isNull(knapsack)){

knapsack = newKnapsack();

knapsack.setUserId(currentUserId);

knapsack.setGiftId(prizeId);

knapsack.setType(Constants.Knapsack.Type.PROP);

knapsack.setNumble(prop.getNum());

knapsackMapper.insertSelective(knapsack);

}else{

knapsack.setNumble(knapsack.getNumble() + prop.getNum());

knapsackMapper.updateByPrimaryKeySelective(knapsack);

}

}

//没进行一轮如果抽到了特殊奖池,那么都要清空幸运值,不然如果是多次抽奖,那么后面的每次都会是特殊道具if(isResetLucky){

//清空幸运值wallet.setLucky(0);

walletMapper.updateByPrimaryKeySelective(wallet);

}else{

//增加 幸运值,每抽奖一次, 幸运值+1wallet.setLucky(wallet.getLucky() + 1);

walletMapper.updateByPrimaryKeySelective(wallet);

}

propList.add(prop);

}

//清空幸运值if(isResetLucky){

wallet.setLucky(0);

walletMapper.updateByPrimaryKeySelective(wallet);

}

result.put("propList", propList);

//封装用户积分、幸运值信息result.put("walletInfo", walletMapper.selectByUserId(currentUserId));

returnResponseVO.succeess(result);

}

/***中奖概率,总概率的多少分之一,如果所有道具的概率总和为100当前奖品的概率是1,那么中奖概率就是百分之一*根据Math.random()产生一个double型的随机数,判断每个奖品出现的概率*@paramdrawPools*@returnrandom:奖品列表drawPools中的序列(drawPools中的第random个就是抽中的奖品),返回中奖的道具ID*/public static intgetPrizeIndex(List drawPools) {

// DecimalFormat df = new DecimalFormat("######0.00");intprizeId = 0;

try{

//计算总权重doublesumWeight = 0;

for(DrawPool drawPool : drawPools){

sumWeight += drawPool.getProbability();

}

//产生随机数doublerandomNumber;

randomNumber = Math.random();

//根据随机数在所有奖品分布的区域并确定所抽奖品doubled1 = 0;

doubled2 = 0;

for(inti=0;i

//依次获取奖品所在的范围//获取当前奖品所在的中奖概率范围 最大值d2 += Double.parseDouble(String.valueOf(drawPools.get(i).getProbability()))/sumWeight;

if(i==0){

d1 = 0;

}else{

//获取上一个奖品所在的中奖概率范围 最大值d1 +=Double.parseDouble(String.valueOf(drawPools.get(i-1).getProbability()))/sumWeight;

}

//如果中奖随机数 大于上一个奖品的最大值 并且小于当前奖品的最大值,那么表示中奖随机数在当前奖品的中奖范围内,当前奖品中奖if(randomNumber >= d1 && randomNumber <= d2){

prizeId = drawPools.get(i).getPropId();

break;

}

}

}catch(Exception e){

System.out.println("生成抽奖随机数出错,出错原因:"+e.getMessage());

}

returnprizeId;

}

}

以上代码,list函数返回抽奖页面的相关信息,luckDraw函数进行抽奖,返回中奖信息,以及积分修改后的信息,getPrizeIndex函数则为具体的抽奖逻辑;

抽奖功能的实现java_Java实现抽奖功能相关推荐

  1. 小程序源码:修复登录大河盲盒小程序源码,实现运营“玩法自由”,超多功能的盲盒型抽奖挖矿程序源码下载

    程序介绍 应用支持哪些类型的商品? 1.实物需邮寄商品,用户领取时填写收货信息,后台发货. 2.虚拟商品,如:教程.课程.图文.图片.下载链接等等. 3.卡密商品,后台添加卡密商品,填写使用方法.批量 ...

  2. 2022新H5拼团抽奖拆盲盒模式源码+功能非常强大

    正文: 这程序有非常详细的演示图,大家自己在本文查看即可. H5拼团抽奖盲盒源码,抽奖拼团玩法,三个房间,每个房间的价格不一样,比如1000的房间,里面的商品是1000以内的,用户购买之后等待开奖,然 ...

  3. 微信字 签到 java_java微信签到功能实现:java做的一个简易的微信签到系统

    java微信签到功能实现,现在微信签到功能很流行,这个签到功能帮助微信用户更好的管理自己的微信公众号,那你想知道java微信签到功能如何实现呢,今天小编就特意为大家分享一个关于java微信签到功能实现 ...

  4. java如何调用微信功能_Java编程调用微信分享功能示例

    本文实例讲述了java编程调用微信分享功能.分享给大家供大家参考,具体如下: 这篇文章介绍如何使用java开发微信分享功能,因为工作,已经开发完成,可使用. 如果想要自定义微信的分享功能,首先在自己的 ...

  5. html 抽奖的页面,js实现网页抽奖实例

    本文实例讲述了js实现网页抽奖的方法.分享给大家供大家参考.具体如下: 这段网页抽奖程序,基于javascript代码实现,简单的演示如何使用JS来实现抽奖功能,点击"开始抽奖"按 ...

  6. php9宫格抽奖程序_使用php控制抽奖系统

    一下观点都是小弟未经深思熟虑的考虑写的,如果不对的地方请指点.... 抽奖系统 俗称 大转盘 或 九宫格抽奖功能,大转盘或九宫格的功能我就不说了,网上插件有很多,也很简单,这里就简单的讲解一下思路 1 ...

  7. 收藏功能_微信强大的收藏功能,你们用了吗?

    在中国说到即时聊天工具,就得说到微信和QQ了,他们都是腾讯旗下的产品,今天麦叔要和大家聊的是微信,去年官方数据显示微信用户已超过10亿,庞大用户群体在使用它,但它的一些功能并不是每个人都会知道,今天麦 ...

  8. SAP MM MRKO功能里的Display与Settle功能之分离?

    SAP MM MRKO功能里的Display与Settle功能之分离? SAP系统里有寄售采购和管道采购的功能,对于与供应商对账与定期结算的业务,提供了标准的事务代码MRKO予以支持.项目实践中,管道 ...

  9. php reids的geo功能,Redis GEO相关命令和功能,你造吗?

    Redis 是一个高性能的key-value数据库,其最大优点就是,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用.同时Redis还提供 ...

最新文章

  1. java 网络编程简单聊天_网络编程之 TCP 实现简单聊天
  2. oracle数据库的详细安装,Oracle 11g数据库详细安装图文教程
  3. python 类-9. 类 — Python 3.9.0 文档
  4. Meet new Sentinel Go committers!
  5. 【程序设计】变量名的命名原则
  6. js中 var a= b || c;
  7. FPGA图像处理基础----直方图均衡化
  8. 腾达ac5第三方固件_腾达AC9的刷固件指南
  9. tftp服务器怎么开启linux,CentOS 6.4 tftp服务器配置--使用tftp下载并启动内核
  10. Netty网络编程第七卷
  11. 为什么计算机关机后自动开机,老司机教你电脑关机后自动开机怎么办
  12. 从程序员到教育工作者
  13. CSS3理解position属性
  14. 三星java遗忘的勇士_顺位不高的无名小辈,敢打敢拼的悍将,永不放弃的代表人物!...
  15. 黑马程序员————高新技术————内省(了解JavaBean)
  16. 联发科有没有高端处理器_联发科官宣,全球第六款7nm处理器来袭,专为游戏而生...
  17. 十种免费网站访问分析工具
  18. java xxtea加密_TEA、XTEA、XXTEA加密解密算法
  19. 【Rhapsody学习笔记(一)】OrionHealth-Rhapsody的组成及常用过滤器
  20. 乳制品追溯系统实现的好处

热门文章

  1. idea取消git托管(删除git文件)
  2. Python:披萨店主页程序练习
  3. Python+appium安装和演示
  4. 性能优化模式-美团技术博客
  5. date parse java_Java LocalDate parse()用法及代码示例
  6. 设计模式-命令模式和组合模式的综合应用
  7. 时间序列R语言操作2——白噪声和随机游走模型
  8. manjaro安装mysql
  9. C++设计一个Bank类,实现银行的创建账户存钱取钱查询交易明细
  10. 写好 Git Commit 信息的 7 个建议