简单的抽奖系统实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Allen202/article/details/78740894

需求|原因
朋友突然给我一个抽奖的一个需求,让我帮他他分析下,需求大致是这样的。
1.发起一个抽象活动,选择几种商品作为这个活动的奖品。
2.商品的信息都已经设置好,名称、数量、单个奖品中奖率(存储整数,以万计。比如存的1,中奖率就是万分之一。)
3.实现用户抽奖,并给出是否中奖,如果中奖,什么奖品?
思路分析
例如有3种奖品 iphone(数量:2,中奖率:1),手电(数量:2,中奖率:20),水笔(数量:3,中奖率:20)
注:中奖率是依照万计算的。就是除以10000。
采用随机数的方式来计算,但怎么产生随机数,才能符合这个概率问题呢。
直接看代码吧

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;

class Prize{
    String id;
    String name;
    //奖品个数
    int sum;
    //中奖率
    int probability;
    //中奖号码
    String winningStr;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getSum() {
        return sum;
    }
    public void setSum(int sum) {
        this.sum = sum;
    }
    public int getProbability() {
        return probability;
    }
    public void setProbability(int probability) {
        this.probability = probability;
    }
    public String getWinningStr() {
        return winningStr;
    }
    public void setWinningStr(String winningStr) {
        this.winningStr = winningStr;
    }

}

/**
 * 抽奖号码类,此类只产生中奖号码,
 * 思路:在发布一个抽奖活动是,为每个奖品产生中奖号码;
 * 当用户来抽奖时,你需要先自己判断奖品数量>0和状态是否存在,如果状态不存在或者数量=0;就直接返回谢谢,未抽中。
 * 如果奖品数量>0;就产生一个随机数(main方法里有例子怎么算出随机数的)。然后比较是否中奖了。中奖之后再去查中了什么奖,否则如果不中奖返回谢谢。
 * 
 * @ClassName:  PrizeRandom   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author LiYuanyuan
 * @date 2017年12月7日 下午1:19:30
 */
public class PrizeRandom {
    //默认最大的概率基数
    private static final int DEFAULT_MAX_RATE_NUM=10000;

    /**
     * 获取奖品的对应的中奖号码
     * @Title: getWinningCode   
     * @Description: TODO(这里用一句话描述这个方法的作用)   
     * @param: @param prizes  奖品对象集合
     * @param: @return  
     * @author LiYuanyuan    
     * @date 2017年12月7日 上午10:24:06
     * @return: Map<String,int[]>      
     * @throws
     */
    public static List<Integer> getAllWinningCode(List<Prize> prizes,int maxRandom,int randomCount){
        //保存生成的中奖号码
        List<Integer> winningNums = new ArrayList<Integer>();
        //产生随机数
        for(int i=0;i<randomCount;i++){
            winningNums.add(getWinningNum(winningNums,maxRandom));
        }
        return winningNums;
    }

    public static Map<String,List<Integer>> getPrizeWinNums(List<Prize> prizes,List<Integer> winningNums, int prizeLSM){
        Map<String,List<Integer>> prizesWinNumMap = new HashMap<String,List<Integer>>();
        //生成中奖号码的个数
        int rateSum = winningNums.size();
        //遍历奖品,分配中奖数
        int index=0;
        for(Prize prize:prizes){
            //奖品的中奖号码个数
            int probabilitySum = prize.getProbability()*prizeLSM;
            //保存奖品分配的中奖数
            List<Integer> prizeWinNums = new ArrayList<Integer>(); 
            //从总的中奖号码中随机获取索引下的value
            int i=0;
            for(;index<rateSum;index++){
                //防止在抽取到相同的index,获取相同的数字。所以
                prizeWinNums.add(winningNums.get(index));
                if(i==probabilitySum-1){
                    break;
                }
                i++;
            } 
            index++;
            prizesWinNumMap.put(prize.getName(),prizeWinNums);
        }
        return prizesWinNumMap;
    }

    /**
     * 获取一个奖品的中奖号码
     * @param winningNumList  保存中奖号码的List集合
     * @param maxRandom  随机数的最大取值范围
     * @return 中奖号码
     */
    private static int getWinningNum(List<Integer> winningNumList, int maxRandom){
        //
        int winningNum = getRandom(maxRandom);
        if(winningNumList.contains(winningNum)){
            winningNum = getWinningNum(winningNumList,maxRandom);
        }
        return winningNum;
    }

    /**
     * 获取一个小于max的随机数
     * @param max 随机数的最大范围 =所有奖品个数的最小公倍数*10000;
     * @return  int 随机数
     */
    public static int getRandom(int max){
        double randomD = Math.random()*max+1;
        String randomStr = String.valueOf(randomD);
        randomStr = randomStr.substring(0, randomStr.lastIndexOf("."));
        return Integer.parseInt(randomStr);
    }




    /**
     * 求最小公倍数
     * @Title: getLSM   
     * @Description: TODO(这里用一句话描述这个方法的作用)   
     * @param: @param rates   参与活动的所有奖品个数List集合
     * @param: @return  
     * @author LiYuanyuan    
     * @date 2017年12月7日 上午10:19:38
     * @return: int      
     * @throws
     */
    public static int getLSM(List<Integer> rates){
        int lsmNum = -1;
        int max = getMaxByList(rates);
        for(int i=max;;i++){
            boolean isExsitLSM = true;
            for(int num : rates){
                if(i%num!=0){
                    isExsitLSM = false;
                    break;
                }
            }
            if(isExsitLSM){
                lsmNum = i;
                break;
            }
        }
        return lsmNum;
    }
    /**
     * 获取List中的最大值
     * @Title: getMaxByList   
     * @Description: TODO(这里用一句话描述这个方法的作用)   
     * @param: @param rates
     * @param: @return  
     * @author LiYuanyuan    
     * @date 2017年12月7日 上午10:19:19
     * @return: int      
     * @throws
     */
    private static int getMaxByList(List<Integer> rates){
        Arrays.sort(rates.toArray());
        return rates.get(rates.size()-1);
    }



    public static void main(String[] args) {

        //初始化一个活动奖品
        List<Prize> prizes = new ArrayList<Prize>();
        Prize prize = new Prize();
        prize.setId("1");
        prize.setName("iphoneX");
        prize.setSum(1);
        prize.setProbability(20);
        prizes.add(prize);

        prize = new Prize();
        prize.setId("2");
        prize.setName("手电");
        prize.setSum(2);
        prize.setProbability(50);
        prizes.add(prize);

        prize = new Prize();
        prize.setId("3");
        prize.setName("水笔");
        prize.setSum(2);
        prize.setProbability(100);
        prizes.add(prize);

        //定义一个保存所有参与抽奖活动A的所有奖品个数集合
        List<Integer> list = new ArrayList<Integer>();
        list.add(1);//iphoneX个数
        list.add(2);//手电个数
        list.add(2);//水笔个数

        //求奖品个数的最小公倍数,利用最小公倍数,算出随机数的最大范围。
        int prizeMinLSMLSM = getLSM(list);
        int maxRandom = prizeMinLSMLSM*DEFAULT_MAX_RATE_NUM;

        //求出,每种奖品在最小公倍数作为分母基数时,分子的大小是多少,也就是占用的概率是多少
        int rateSum = 0;
        for(Prize prizee:prizes){
            rateSum+=(prizee.getProbability()*prizeMinLSMLSM);
        }

        //1.建立一个抽奖活动A时,生成活动奖品号码
        //获取所有的中奖号码
        List<Integer> allWinningCodes = getAllWinningCode(prizes,maxRandom,rateSum);
        //分配中奖号码
        Map<String,List<Integer>> prizesWinNumMap = getPrizeWinNums(prizes, allWinningCodes, prizeMinLSMLSM);
        System.out.println("本次抽奖活动A的所有奖品幸运号码:");
        System.out.println(JSON.toJSON(prizesWinNumMap));


        //2.用户抽奖的时候

        boolean isLuck = false;//是否中奖
        int i = 1;//模仿许多用户抽奖
        int luckCount = 0;//中奖次数
        while(!isLuck){
            //产生一个随机号码
            int luckNum = getRandom(maxRandom);
            System.out.println("用户 李园园第"+i+"次抽中的号码为:"+luckNum);
            //随机号码是否存在于奖品号码里
            if(allWinningCodes.contains(luckNum)){
                //遍历奖品的中奖号码,查找中奖了那个奖品
                for(String key:prizesWinNumMap.keySet()){
                    if(prizesWinNumMap.get(key).contains(luckNum)){
                        //遍历奖品
                        for(Prize prizee:prizes){
                            if(prizee.getName().equals(key)){
                                //判断奖品数量
                                if(prizee.getSum()>0){
                                    prizee.setSum(prizee.getSum()-1);
                                    System.out.println("恭喜中奖了:"+key+ " 剩余奖品数:"+prizee.getSum());
                                    luckCount++;
                                }else{
                                    System.out.println("---奖品"+key+"派发完了,谢谢惠顾");
                                    isLuck=true;
                                }
                            }
                        }
                    }
                }
            }else{
                System.out.println("谢谢惠顾");
            }
            i++;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Allen202/article/details/78740894