砸金蛋java代码_java实现砸金蛋抽奖功能

本文实例为大家分享了java实现砸金蛋抽奖的具体代码,供大家参考,具体内容如下

代码如下

需求:用户每一次砸金蛋,抽中一等奖的概率为2% 二等奖10% 三等奖18% 四等奖70%。

累计砸第n次时必抽中x等奖以上的奖品。比如,累计砸第5次,则此次必中二等奖及以上的奖品。且配置的此次必中中奖概率不一样。

/**

* 金蛋抽奖

* userId : 抽奖用户ID

* consumeType : 抽奖消耗的物品 1:金币 2:次数

*/

@Override

public Map eggsLottery(Integer userId, Integer consumeType) {

/*******first : check user ************/

checkUserIsLock(userId);

logger.info("userId {} start lottery -eggs.", userId);

Jedis jedis = RedisPool.getJedis();

try {

//查询活动开关

String hget = jedis.hget(Rkey.SMASH_GOLD_EGGS_GLOBAL_CONFIG, "status");

if (null == hget || "0".equals(hget)) {

throw new BusiException(E.INVALID_PARAMETER, "活动暂未开启,敬请期待");

}

//check lottery type

Long consumeScore = 0L;

/**score lottery**/

consumeScore = jedis.hincrBy(Rkey.SMASH_GOLD_EGGS_GLOBAL_CONFIG, "consumeGoldScore", 0);

if (consumeScore < 1) {

throw new BusiException(E.EGGS_ACTIVITY_CONFIG_EXCEPTION, "活动配置有误!");

}

long surScore = goldWalletMapper.selectAmountGoldByUserId(userId);

surScore = surScore - consumeScore;

if (surScore < 0) {

throw new BusiException(E.SCORE_NOT_ENOUGH, "您的金币不足");

}

// 砸金蛋之前扣除金币

Date now = new Date();

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 (Exception e) {

throw e;

}

return map;

} finally {

RedisPool.returnJedis(jedis);

}

}

/**

* 抽奖 begin----

*/

private Map lottery(Jedis jedis, Date now, Integer userId, Long consumeScore) {

Map map = new HashMap();

// 判断本次是否是必中? jackpotType=1: 不是 2:是必中

Integer jackpotType = 1;

// 剩余次数

Integer freeCount = 0;

String countStr = jedis.hget(Rkey.SMASH_GOLD_EGGS_USER_WIN_COUNT, userId.toString());

if (StringUtils.isNotEmpty(countStr)) {

Integer count = Integer.valueOf(countStr);

String whenAwardCount = jedis.hget(Rkey.SMASH_GOLD_EGGS_GLOBAL_CONFIG, "whenAwardCount");

if (StringUtils.isEmpty(whenAwardCount)) {

throw new BusiException(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);

}

}

// 根据配置得到总的奖品数量

Integer totalCount = 0;

if (jackpotType == 1) {

totalCount = getAwardTotalCount(1);

} else {

totalCount = getAwardTotalCount(2);

}

Integer award = getRandomNumber(totalCount);

// 看落在哪个区间

Integer awardId = getWinAwardId(award, jackpotType);

BsGoldEggsConfig goldEggsConfig = goldEggsConfigMapper.selectById(awardId);

if (goldEggsConfig == null) {

throw new BusiException(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 {} win award {}, 奖励金币:{}, 随机生成抽奖数:{}", userId, goldEggsConfig.getDescribe(), goldEggsConfig.getGoldCount(), award);

// 抽奖结束 action:

if (jackpotType == 1) {

// 抽奖结束后 记录累计抽奖次数 +1

// 必中 不加

jedis.hincrBy(Rkey.SMASH_GOLD_EGGS_USER_WIN_COUNT, userId.toString(), 1);

}

// 奖励金币结算

Date now1 = new Date();

lotteryAddGold(goldEggsConfig.getGoldCount().longValue(), now1, userId);

return map;

}

/**

* 得到中奖id

*

* @param award : 随机生成的抽奖数字

* @return

*/

private Integer getWinAwardId(Integer award, Integer jackpotType) {

List goldEggsConfigList = goldEggsConfigMapper.queryAllList();

if (goldEggsConfigList == null || goldEggsConfigList.size() < 4) {

throw new BusiException(E.INVALID_REQUEST, "请先完成砸金蛋奖品配置!");

}

Integer[] weight = new Integer[4];

if (jackpotType == 1) {

// 基础抽奖

for (int i = 0; i < goldEggsConfigList.size(); i++) {

weight[i] = goldEggsConfigList.get(i).getBaseWeight();

}

} else {

// 必中抽奖

for (int i = 0; i < goldEggsConfigList.size(); i++) {

weight[i] = goldEggsConfigList.get(i).getWinWeight();

}

}

// 判断随机数落在了哪个区间 左开右闭 ---------- 这里如果用redis的set来做区间?如何实现?

Integer awardId = 1;

if (0 < award && award <= weight[0]) {

// 一等奖

awardId = 1;

} else if (weight[0] < award && award <= (weight[0] + weight[1])) {

// 二等奖

awardId = 2;

} else if ((weight[0] + weight[1]) < award && award <= (weight[1] + weight[2])) {

// 三等奖

awardId = 3;

} else {

// 四等奖

awardId = 4;

}

return awardId;

}

/**

* 获取1-max范围内 一个随机数

*

* @param max

* @return

*/

private Integer getRandomNumber(Integer max) {

int i = (int) (Math.random() * max + 1);

return i;

}

下面是用奖池写的一个算法 读者可忽略,博主只是记录一下。

思路:

根据需求:

1.生成两类奖池(普通奖池,和必中奖池),中奖概率不一样!为了保证概率正确,我们生成100组(1-100)的数字,随机打乱放入redis中,作为一个奖池。

2.生成中奖区间,放入redis

3.每次用户砸金蛋,从奖池里面取一个数,

4.判断该数在哪个中奖区间

/**

* 抽奖 begin---- 该方法废除

*/

private Map lottery2(Jedis jedis, Date now, Integer userId, Long consumeScore) {

// 从奖池中拿出第一个奖品

String jackpotKey = Rkey.SMASH_GOLD_EGGS_JACKPOT_ + "one";

String baseWinLimitKey = Rkey.SMASH_GOLD_EGGS_AWARD_WIN_LIMIT_BASE;

String nextWinLimitKey = Rkey.SMASH_GOLD_EGGS_AWARD_WIN_LIMIT_NEXT;

Map map = new HashMap();

// 奖池存在 且奖池不为空

String awardFlag = jedis.lpop(jackpotKey); // 如:20

Integer award = Integer.valueOf(awardFlag);

//

if (!StringUtils.isEmpty(awardFlag)) {

// 判断该奖品的等级

// 这里是有问题的 博主后面纠正

Set winLimitSet = jedis.zrange(baseWinLimitKey, 0, award - 1);

if (winLimitSet != null && !winLimitSet.isEmpty()) {

Integer size = winLimitSet.size();

List list = new ArrayList(winLimitSet);

// 取区间最后一个

String lastAwardLevel = String.valueOf(list.get(size - 1));

// 获取奖品info

Integer id = null;

if ("one".equals(lastAwardLevel)) {

id = 1;

} else if ("two".equals(lastAwardLevel)) {

id = 2;

} else if ("three".equals(lastAwardLevel)) {

id = 3;

} else if ("four".equals(lastAwardLevel)) {

id = 4;

}

BsGoldEggsConfig goldEggsConfig = goldEggsConfigMapper.selectById(id);

if (goldEggsConfig == null) {

throw new BusiException(E.INVALID_REQUEST, "奖品信息未找到");

}

map.put("userId", userId);

map.put("awardId", id);

map.put("awardName", goldEggsConfig.getDescribe());

map.put("goldCount", goldEggsConfig.getGoldCount());

logger.info("userId {} win award {}, 奖励金币:{}, 随机生成抽奖数:{}", userId, goldEggsConfig.getDescribe(), goldEggsConfig.getGoldCount(), award);

}

}

return map;

}

/**

* 生成奖池

*

* @param jackpotType : 奖池类型 1:普通奖池 2:必中奖池

* @param jackpotSort :奖池序号 1,2,3...... 如普通奖池1,普通奖池2,

*/

@Override

public void addAwardToJackpot(Integer jackpotType, Integer jackpotSort) {

// 存放奖池数据

List awadList = new ArrayList<>();

// 奖池key

String jackpotKey = "";

String jackpotTypeToStr = "";

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);

Jedis jedis = RedisPool.getJedis();

try {

if (jedis.exists(jackpotKey)) {

// 判断奖池中是否还有奖品

Long length = jedis.llen(jackpotKey);

if (length <= 0) {

// 奖池空了,重新放入奖品

logger.info("{}奖池{}空了,重新放入奖品。。。。。", jackpotTypeToStr, jackpotSort);

// 根据配置得到总的奖品数量

Integer totalCount = getAwardTotalCount(1);

setSingleAwardToJackpot(awadList, jedis, jackpotKey, totalCount);

}

} else {

// 直接生成奖池

logger.info("{}奖池{}不存在,直接放入奖品。。。。。", jackpotTypeToStr, jackpotSort);

Integer totalCount = getAwardTotalCount(1);

setSingleAwardToJackpot(awadList, jedis, jackpotKey, totalCount);

}

} finally {

RedisPool.returnJedis(jedis);

}

}

/**

* 获取奖池奖品数量

*

* @param type 奖池类型:1:普通奖池 2:必中奖池

* @return

*/

Integer getAwardTotalCount(Integer type) {

List goldEggsConfigList = goldEggsConfigMapper.queryAllList();

if (goldEggsConfigList == null || goldEggsConfigList.size() < 4) {

throw new BusiException(E.INVALID_REQUEST, "请先完成砸金蛋奖品配置!");

}

Integer totalCount = 0;

if (type == 1) {

// 普通奖池奖品数量

for (BsGoldEggsConfig goldEggsConfig : goldEggsConfigList) {

totalCount += goldEggsConfig.getBaseWeight();

}

} else {

// 必中奖池数量

Jedis jedis = RedisPool.getJedis();

try {

String mustAwardLevel = jedis.hget(Rkey.SMASH_GOLD_EGGS_GLOBAL_CONFIG, "mustAwardLevel");

if (StringUtils.isEmpty(mustAwardLevel)) {

throw new BusiException(E.INVALID_REQUEST, "请先完成砸金蛋奖品配置!");

}

for (int i = 0; i < Integer.valueOf(mustAwardLevel); i++) {

totalCount += goldEggsConfigList.get(i).getWinWeight();

}

} finally {

RedisPool.returnJedis(jedis);

}

}

return totalCount;

}

/**

* @param awadList

* @param jedis

* @param jackpotKey

* @param totalCount 总的奖品个数 比如一等奖10个,二等奖20个,三等奖30,四等奖40 则totalCount = 10+20+30+40=100

*/

private void setSingleAwardToJackpot(List awadList, Jedis jedis, String jackpotKey, Integer totalCount) {

// 1.生成 100组 [1-100] 随机数 awadList

for (int i = 0; i < 2; i++) {

List list = getOneToHundredNumber(totalCount);

for (Integer j : 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

*/

private List getOneToHundredNumber(Integer end) {

// 起始数字

int start = 1;

// 生成数字的个数

// int end = 100;

// 生成1,2,3,4,5...100

List list = Stream.iterate(start, item -> item + 1).limit(end).collect(Collectors.toList());

return list;

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 Android 金蛋功能代码示例: 1. 在布局文件中添加一个 ImageView 用于显示金蛋图片和一个 TextView 用于显示剩余次数: ```xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/egg_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/golden_egg" android:layout_centerInParent="true" /> <TextView android:id="@+id/remaining_count" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/egg_image" android:layout_centerHorizontal="true" android:text="Remaining count: 3" /> </RelativeLayout> ``` 2. 在 Activity 中定义变量并初始化布局: ```java public class MainActivity extends AppCompatActivity { private ImageView eggImage; private TextView remainingCount; private int count = 3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); eggImage = findViewById(R.id.egg_image); remainingCount = findViewById(R.id.remaining_count); } // ... } ``` 3. 添加一个点击事件监听器,点击后减少剩余次数,并根据剩余次数显示不同的提示信息: ```java public class MainActivity extends AppCompatActivity { // ... @Override protected void onCreate(Bundle savedInstanceState) { // ... eggImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (count > 0) { count--; remainingCount.setText("Remaining count: " + count); if (count == 0) { Toast.makeText(MainActivity.this, "No more attempts!", Toast.LENGTH_SHORT).show(); } else if (count == 1) { Toast.makeText(MainActivity.this, "Last attempt!", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "Keep Going!", Toast.LENGTH_SHORT).show(); } } } }); } // ... } ``` 这个简单的示例中,点击金蛋图片可以金蛋,每次成功中后会减少一次剩余次数并显示不同的提示信息,当剩余次数为 0 时,点击事件将不再执行。你可以根据需要对代码进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值