Java实现仿微信红包分配规则

最近过年发红包拜年成为一种新的潮流,作为程序猿对算法的好奇远远要大于对红包的好奇,这里介绍一种自己想到的一种随机红包分配策略,还请大家多多指教。

算法介绍

一、红包金额限制

对于微信红包,我们知道没人随机的最小红包是1分,最大金额是200元,这里我们同样来设置红包的范围,下面代码我们统一金钱的单位为分。

//最小红包额度
private static final int MINMONEY = 1;
//最大红包额度
private static final int MAXMONEY = 200 * 100;

二、判断红包金额是否合法
      注意这一步伴随着整个算法,我们不仅要在分配红包之前要判断金额是否合法,同样要在每个人暂定随机金额后也要判断剩余的金额是否合法。

private boolean isRight(int money, int count) {
 double avg = money / count;
 if (avg < MINMONEY) {
 return false;
 }
 if (avg > MAXMONEY) {
 return false;
 }
 return true;
}

三、随机产生一个红包
      这里我们采用随机的方式产生一个在MINMONEY和MAXMONEY之间的一个红包,产生红包之后,我们需要判断剩余的钱是否是合法红包,如果不是合法红包,我们就重新产生分配方案,在重新产生分配方案的时候,我们需要确定一个事情,是产生的红包过大还是过小,如果红包过大,下次就随机一个小值到本次红包金额的一个红包,如果红包金额过小,我们就产生一个红包金额到大值的一个红包。

private int random(int money, int minS, int maxS, int count) {
 //红包数量为1,直接返回金额
 if (count == 1) {
 return money;
 }
 //如果最大金额和最小金额相等,直接返回金额
 if (minS == maxS) {
 return minS;
 }
 int max = maxS > money ? money : maxS;
 //随机产生一个红包
 int one = ((int)Math.rint(Math.random() * (max - minS) + minS)) % max + 1;
 int money1 = money - one;
 //判断该种分配方案是否正确
 if (isRight(money1, count -1)) {
 return one;
 } else {
 double avg = money1 / (count - 1);
 if (avg < MINMONEY) {
 //递归调用,修改红包最大金额
 return random(money, minS, one, count);
 }else if (avg > MAXMONEY) {
 //递归调用,修改红包最小金额
 return random(money, one, maxS, count);
 }
 }
 return one;
}

四、实现红包分配
      这里为了避免某一个红包占用大量资金,我们需要设定非最后一个红包的最大金额,我们把他设置为红包金额平均值的N倍;有了一、二、三中的方法,我们就可以来实现红包的分配了。

//每个红包最大是平均值的倍数
private static final double TIMES = 2.1; 

public List<Integer> splitRedPackets(int money, int count) {
 if (!isRight(money, count)) {
 return null;
 }
 List<Integer> list = new ArrayList<Integer>();
 //红包最大金额为平均金额的TIMES倍
 int max = (int) (money * TIMES / count);
 max = max > MAXMONEY ? MAXMONEY : max;
 for (int i = 0; i < count; i++) {
 int one = random(money, MINMONEY, max, count - i);
 list.add(one);
 money -= one;
 }
 return list;
}

红包分配方案评估

上面介绍了红包的基本算法,下面我们就对算法进行一次验证,假设有一个200元100份的红包,我们来看一下最后的分配方案。

完整代码

 /**
 *@Description:
 */
package com.lulei.weixin.util; 

import java.util.ArrayList;
import java.util.List; 

import com.lulei.util.JsonUtil; 

public class RedPacketUtil {
 //最小红包额度
 private static final int MINMONEY = 1;
 //最大红包额度
 private static final int MAXMONEY = 200 * 100;
 //每个红包最大是平均值的倍数
 private static final double TIMES = 2.1; 

 /**
 * @param money
 * @param count
 * @return
 * @Author:lulei
 * @Description: 拆分红包
 */
 public List<Integer> splitRedPackets(int money, int count) {
 if (!isRight(money, count)) {
 return null;
 }
 List<Integer> list = new ArrayList<Integer>();
 //红包最大金额为平均金额的TIMES倍
 int max = (int) (money * TIMES / count);
 max = max > MAXMONEY ? MAXMONEY : max;
 for (int i = 0; i < count; i++) {
 int one = random(money, MINMONEY, max, count - i);
 list.add(one);
 money -= one;
 }
 return list;
 } 

 /**
 * @param money
 * @param minS
 * @param maxS
 * @param count
 * @return
 * @Author:lulei
 * @Description: 随机红包额度
 */
 private int random(int money, int minS, int maxS, int count) {
 //红包数量为1,直接返回金额
 if (count == 1) {
 return money;
 }
 //如果最大金额和最小金额相等,直接返回金额
 if (minS == maxS) {
 return minS;
 }
 int max = maxS > money ? money : maxS;
 //随机产生一个红包
 int one = ((int)Math.rint(Math.random() * (max - minS) + minS)) % max + 1;
 int money1 = money - one;
 //判断该种分配方案是否正确
 if (isRight(money1, count -1)) {
 return one;
 } else {
 double avg = money1 / (count - 1);
 if (avg < MINMONEY) {
 //递归调用,修改红包最大金额
 return random(money, minS, one, count);
 }else if (avg > MAXMONEY) {
 //递归调用,修改红包最小金额
 return random(money, one, maxS, count);
 }
 }
 return one;
 } 

 /**
 * @param money
 * @param count
 * @return
 * @Author:lulei
 * @Description: 此种红包是否合法
 */
 private boolean isRight(int money, int count) {
 double avg = money / count;
 if (avg < MINMONEY) {
 return false;
 }
 if (avg > MAXMONEY) {
 return false;
 }
 return true;
 } 

 public static void main(String[] args) {
 // TODO Auto-generated method stub
 RedPacketUtil util = new RedPacketUtil();
 System.out.println(JsonUtil.parseJson(util.splitRedPackets(20000, 100)));
 }
} 

更多精彩内容请点击《Android微信开发教程汇总》,《java微信开发教程汇总》欢迎大家学习阅读。

以上就是本文的全部内容,希望对大家学习java程序设计有所帮助。

(0)

相关推荐

  • java微信公众号开发案例

    微信公众号开发一般是针对企业和组织的,个人一般只能申请订阅号,并且调用的接口有限,下面我们就来简单的描述下接入公众号的步骤: 1.首先你需要一个邮箱在微信公众号平台进行注册:      注册的方式有订阅号.公众号.小程序和企业号,个人我们这里只能选择订阅号 2.注册完后,我们登录到公众号平台--->开发--->基本配置,这里需要填写URL和token,URL就是我们使用服务器的接口: 3.Java Web服务器程序编译好且在服务器上部署可以运行的话,可在微信公众号进行在线接口调试: 1).选择

  • java开发微信分享到朋友圈功能

    微信分享功能开发 用了一天时间,把微信发送给朋友和分享到朋友圈功能开发出来,在这里给大家分享一下,避免大家走弯路. 一.服务器端程序 package com.wiimedia.controller; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.ParseException; import

  • 微信java开发之实现微信主动推送消息

    1.拉取access_token2.拉取用户信息3.主动推送消息4.接口貌似要申请权限5.依赖httpclient4.2.3 和jackson 2.2.1 复制代码 代码如下: public class WeixinAPIHelper { /**  * 获取token接口  */ private String getTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=

  • java实现微信支付(服务端)

    废话不多说,直接看代码. RequestHandler requestHandler = new RequestHandler(super.getRequest(),super.getResponse()); //获取token //两小时内有效,两小时后重新获取 Token = requestHandler.GetToken(); //更新token 到应用中 requestHandler.getTokenReal(); System.out.println("微信支付获取token=====

  • Java通过JsApi方式实现微信支付

    要使用JsApi进行微信支付,首先要从微信获得一个prepay_id,然后通过调用微信的jsapi完成支付,JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回.由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分. 示例代码如下: function onBridgeReady(){ WeixinJSBridge

  • java微信公众号开发(搭建本地测试环境)

    俗话说,工欲善其事,必先利其器.要做微信公众号开发,两样东西不可少,那就是要有一个用来测试的公众号,还有一个用来调式代码的开发环境. 测试公众号 微信公众号有订阅号.服务号.企业号,在注册的时候看到这样的信息,只有订阅号可以个人申请,服务号和企业号要有企业资质才可以.这里所说的微信公众号开发指的是订阅号和服务号. 另外,未认证的个人订阅号有一些接口是没有权限的,并且目前个人订阅号已不支持微信认证,也就是说个人订阅号无法调用一些高级的权限接口,下图就是一个未认证的个人订阅号所具备权限列表,像生成二

  • Java编程调用微信分享功能示例

    本文实例讲述了Java编程调用微信分享功能.分享给大家供大家参考,具体如下: 这篇文章介绍如何使用java开发微信分享功能,因为工作,已经开发完成,可使用. 如果想要自定义微信的分享功能,首先在自己的页面内首先使用AJAX.下面我具体举例. 首先是在页面内写入请求后台的AJAX /** * 调用微信分享接口 * */ public void WXConfig(){ String url = getPara("href"); WXConfigController scan = new W

  • 微信支付H5调用支付详解(java版)

    最近项目需要微信支付,然后看了下微信公众号支付,,虽然不难,但是细节还是需要注意的,用了大半天时间写了个demo,并且完整的测试了一下支付流程,下面分享一下微信公众号支付的经验. 一.配置公众号微信支付  需要我们配置微信公众号支付地址和测试白名单. 比如:支付JS页面的地址为 http://www.xxx.com/shop/pay/ 那此处配置www.xxx.com/shop/pay/ 二.开发流程 借用微信公众号支付api(地址 http://pay.weixin.qq.com/wiki/d

  • 第三方网站微信登录java代码实现

    前两个星期在公司中的项目加上了微信登录.绑定的功能,在这里做个记录! 一.开发前知识 1.微信开放平台与微信公众平台的区别 1.1 微信公众平台: ① 地址:https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN ② 微信公众平台面向的是普通的用户,比如自媒体和媒体,企业官方微信公众账号运营人员使用,当然你所在的团队或者公司有实力去开发一些内容,也可以调用公众平台里面的接口,比如自定义菜单,自动回复,查询功能. 1.2

  • Java开发微信公众号接收和被动回复普通消息

    上篇说完了如何接入微信公众号,本文说一下微信公众号的最基本功能:普通消息的接收和回复.说到普通消息,那么什么是微信公众号所定义的普通消息呢,微信开发者文档中提到的接收的普通消息包括如下几类: 1.文本消息 2.图片消息 3.语音消息 4.视频消息 5.小视频消息 6.地理位置消息 7.链接消息(被动回复的消息) 被动回复的普通消息包括: 1.回复文本消息 2.回复图片消息 3.回复语音消息 4.回复视频消息 5.回复音乐消息 6.回复图文消息 其实接收消息和被动回复消息这两个动作是不分家的,这本

  • java开发微信公众号支付

    最近做了微信公众号支付的开发,由于是第一次做也摸索了几天的时间,也只是达到了实现功能的水平,并没有太多考虑到性能问题,所以这篇文章比较适合初学者. 微信公众号支付的总体其实很简单,大致就分为三步.第一步需要获取用户授权:第二步调用统一下单接口获取预支付id:第三步H5调起微信支付的内置的js.下面介绍具体每一步的开发流程. 一    首先要明确微信公众号支付属于网页版支付,所以相较于app的直接调取微信支付要多一步微信授权.也就是需要获取用户的openid.微信公众号使用的交易类型是JSAPI,

  • java实现微信公众平台自定义菜单的创建示例

    复制代码 代码如下: import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL; import org.json.JSONObject; public class MenuUtil { /**  * 获得ACC

随机推荐