美文网首页
【Java 实战】实现大转盘抽奖

【Java 实战】实现大转盘抽奖

作者: 猫的树 | 来源:发表于2021-12-20 15:07 被阅读0次

项目场景

实现一个大转盘抽奖的功能,能后台自定义奖项,各奖项中奖概率,奖品数量,当日抽奖最大次数等。

一、设计思路

这里简单分享下思路:

1.奖品中奖概率

所有参与抽奖的奖项中奖概率之和为 1

2.抽奖规则

这里首先需要明确如何中奖?

一般来说是生成随机数,然后将随机数与奖品的中奖概率相比较,如果小于中奖概率则中奖。

但是,如果每个奖项或者几个奖项的概率一样,上面的方法就会出现每次抽奖,中奖都是同一个奖品的情况

所以我们采用中奖概率累加的方法,如图所示:



抽奖规则:

  • 获取该游戏的奖品列表,按照中奖概率升序排列 (可以不用排序)
  • 奖品列表中的概率为累加概率,需要按照添加进列表的顺序进行累加
  • 生成一个0-1的随机数,与设置好的奖品概率循环比较
  • 若随机数小于概率值,则抽中该奖项

3.奖品发放

在设置奖品的时需要设置类型,例如:优惠券积分商品(实物)虚拟商品 等等。

每个类型的奖品发放规则不同,这里可以利用Java多态的特性建立一个工厂类,用不同的实现类来分别实现不同类型的奖品的中奖处理逻辑

这里由于将使用的微服务,所以直接通过feign调用对应的服务方法

二、数据库设计

1.转盘游戏表

存储转盘抽奖信息

字段 描述
id(varchar) 主键id
name(varchar) 活动名称
start_time(datetime) 开始时间
end_time(datetime) 结束时间
description(varchar) 描述
day_limit(int) 单人当天限制次数 0:代表不限制
single_limit(int) 单人总次数限制 0:代表不限制
state(int) 活动状态,1 开启 2 关闭

2.奖品表

存储抽奖奖品信息

字段 描述
id(varchar) 主键id
game_id(varchar) 游戏id
prize_type(int) 奖品类型(1优惠券,2商品,3积分,4谢谢参与)
prize_name(varchar) 奖品名字
prize_id(varchar) 奖品id
prize_value(int) 奖品值(数量)
ratio(double) 中奖几率
current_num(int) 当前命中
max_num(int) 最大中奖数 0:代表不限制

3.抽奖记录表

存储抽奖记录信息

字段 描述
id(varchar) 主键id
game_id(varchar) 游戏id
user_id(datetime) 用户id
user_name(datetime) 用户名
draw_time(varchar) 抽奖时间
is_hit(int) 是否中奖 0:未中奖 1:中奖
hit_prize(varchar) 中奖奖品
is_send(int) 是否发放 1未发放,2 已发放 3 发放失败
send_msg(text) 发放结果

三、业务逻辑

1.提供接口

(1)获取转盘游戏
(2)获取用户的抽奖记剩余次数
(3)参与转盘抽奖
(4)抽奖记录

2.核心代码

抽奖逻辑代码

// 获取奖品信息列表
List<Entity> prizeList = service.list();
// 奖品列表中的概率为累加概率
// 需要按照添加进列表的顺序进行累加,为了数据处理方便中奖几率*100
double sum = 0;
List<Entity> newList = new ArrayList<>();
for (int i = 0; i < prizeList.size(); i++) {
    Entity entity = prizeList.get(i);
    Entity newEntity = new Entity();
    BeanUtils.copyProperties(entity, newEntity);
    sum = sum + (entity.getRatio() * 100);
    newEntity.setRatio(sum);
    newList.add(newEntity);
}

// 生成一个随机数
Random random = new Random();
Double userSelect = random.nextDouble() * 10000;
for (Entity prize : prizeList) {
    // 随机数小于中奖几率,则中奖
    if (userSelect < prize.getRatio()) {
        // 最大中奖数(0:代表不限制次数)
        int maxNum = prize.getMaxNum();
        // 判断游戏奖品当前中奖数及最大中奖数
        if (maxNum != 0 && maxNum <= prize.getCurrentNum()) {
            // 超过最大中奖数则不中
            break;
        } else {
            return prize;
        }
    }
}
// 谢谢参与
List<Entity> prize = prizeList.stream().filter(item -> item.getPrizeType() == 4).collect(Collectors.toList());
if (prize.size() > 0) {
    return prize.get(0);
}
return null;

抽奖发放:根据抽中的奖品类型调用对应的服务进行奖品发放;(比如抽中优惠券,就调用优惠券的服务进行发放)

int type = prize.getPrizeType();
try {
    switch (type) {
        // 发放优惠券
        case 1:
            ApiResult res = couponFeign.sendCouponToUser(rentId, userId, prize.getPrizeId(), prize.getPrizeValue());
            // 其他业务处理
            break;
        // 发放商品
        case 2:
            break;
        // 发放积分
        case 3:
            ApiResult res2 = pointFeign.addPointToUser(rentId, gameId, userId, prize.getPrizeValue());
            // 其他业务处理
            break;
        // 谢谢参与
        case 4:
            break;
        default:
            break;
    }
} catch (Exception e) {
    e.printStackTrace();
}

注意事项:抽奖容易出现并发问题,所以在抽奖的地方,需要加上分布式锁,这里使用Redis官方推荐的Java版的Redis客户端Redisson中的分布式锁功能

RLock lock = redisson.getLock("turntable:" + gameId);
try {
    // 指定超时时间 
    if (lock.tryLock(10, TimeUnit.SECONDS)) {
        // 抽奖业务处理
    }

} finally {
    lock.unlock();
}

创作不易,关注、点赞就是对作者最大的鼓励,欢迎在下方评论留言
定期分享Java知识,一起学习,共同成长,期待您的关注!

相关文章

  • 【Java 实战】实现大转盘抽奖

    项目场景 实现一个大转盘抽奖的功能,能后台自定义奖项,各奖项中奖概率,奖品数量,当日抽奖最大次数等。 一、设计思路...

  • php实现刮刮卡大转盘抽奖概率

    php实现刮刮卡大转盘抽奖概率 本文实例为大家分享了php中奖概率算法,可用于刮刮卡,大转盘等抽奖算法,用法很简单...

  • 小程序实现大转盘,九宫格抽奖,带跑马灯效果

    基本实现功能 1,小程序仿天猫超市大转盘 2,九宫格转盘抽奖 3,积分抽奖 4,抽到的积分随机生成 5,抽奖结果可...

  • react实现抽奖大转盘

    先看一下实现的效果(这样才有动力) 1、html代码 2、绘制圆盘 2、绘制奖品canvas绘制都是从水平出开始绘...

  • 小程序的大转盘活动怎么做?

    日常生活中最常见的抽奖活动莫过于大转盘抽奖了吧,无论线上线下。大转盘抽奖活动具有多样性、并可开展基于粘性维护的活动...

  • 微信小程序幸运大转盘制作教程

    幸运大转盘抽奖方式是我见过最常用的抽奖方式了,这种方式简单,直接,让人看着兴奋。那么,幸运大转盘微信小程序怎么制作...

  • canvas大转盘

    下面再介绍一个canvas实例,使用canvas技术实现一个大转盘,在抽奖中用的比较多,实现后的效果如果所示: 第...

  • 连中三元

    幸运大转盘,抽奖领红包,雨露来听歌,胜利哒凯旋。

  • 微信小程序大转盘抽奖

    微信小程序大转盘抽奖 说明看到过太多骗点击量的大转盘抽奖,也写一个玩玩 需求 一个转盘界面 闪动的小点 奖品背景颜...

  • vue适配3到8个大转盘抽奖

    vue实现适配奖品不固定的大转盘抽奖,里面的实现代码就是vue+js,不需要jq,原理就是根据接口传过来的奖品数量...

网友评论

      本文标题:【Java 实战】实现大转盘抽奖

      本文链接:https://www.haomeiwen.com/subject/nalzfrtx.html