Java實現抽獎功能


主要根據概率返回每次抽到的獎品,
以下是抽獎工具類

package com.ruoyi.project.dy.utils;

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

/**
 * @description:
 *  抽獎工具類,概率和可以不等於1
 *  概率為百分數去掉百分號的部分,如10%,則為10
 *  抽獎操作如下:
 *  1.輸入抽獎概率集合,【抽獎概率集合為{10.0, 20.0, 30.0}】
 *  2.生成連續集合,       【生成的連續集合為{(0.0, 10.0],(10.0, 30.0],(30.0, 60.0]}】
 *  3.生成隨機數,          【生成方法為 random.nextDouble() * maxElement】
 *  4.判斷隨機數在哪個區間內,返回該區間的index【生成了隨機數12.001,則它屬於(10.0, 30.0],返回 index = 1】
 *
 *  */
public class LotteryUtil {
    /**
     * 定義一個連續集合
     * 集合中元素x滿足:(minElement,maxElement]
     * 數學表達式為:minElement < x <= maxElement
     *
     */
    public class ContinuousList {

        private double minElement;
        private double maxElement;

        public ContinuousList(double minElement, double maxElement){
            if(minElement > maxElement){
                throw new IllegalArgumentException("區間不合理,minElement不能大於maxElement!");
            }
            this.minElement = minElement;
            this.maxElement = maxElement;
        }

        /**
         * 判斷當前集合是否包含特定元素
         * @param element
         * @return
         */
        public boolean isContainKey(double element){
            boolean flag = false;
            if(element > minElement && element <= maxElement){
                flag = true;
            }
            return flag;
        }

    }

    private List<ContinuousList> lotteryList;
    //概率連續集合
    private double maxElement;
    //這里只需要最大值,最小值默認為0.0

    /**
     * 構造抽獎集合
     * @param list 為獎品的概率
     */
    public LotteryUtil(List<Double> list){
        lotteryList = new ArrayList<ContinuousList>();
        if(list.size() == 0){
            throw new IllegalArgumentException("抽獎集合不能為空!");
        }
        double minElement = 0d;
        ContinuousList continuousList = null;
        for(Double d : list){
            minElement = maxElement;
            maxElement = maxElement + d;
            continuousList = new ContinuousList(minElement, maxElement);
            lotteryList.add(continuousList);
        }
    }

    /**
     * 進行抽獎操作
     * 返回:獎品的概率list集合中的下標
     */
    public int randomColunmIndex(){
        int index = -1;
        Random r = new Random();
        double d = r.nextDouble() * maxElement;
        //生成0-1間的隨機數
        if(d == 0d){
            d = r.nextDouble() * maxElement;
            //防止生成0.0
        }
        int size = lotteryList.size();
        for(int i = 0; i < size; i++){
            ContinuousList cl = lotteryList.get(i);
            if(cl.isContainKey(d)){
                index = i;
                break;
            }
        }
        if(index == -1){
            throw new IllegalArgumentException("概率集合設置不合理!");
        }
        return index;

    }

    public double getMaxElement() {
        return maxElement;
    }

    public List<ContinuousList> getLotteryList() {
        return lotteryList;
    }
    public void setLotteryList(List<ContinuousList> lotteryList) {
        this.lotteryList = lotteryList;
    }

}

該工具類的基本思想是,將抽獎概率分布到數軸上,如現有三個抽獎概率10、20、30,將三者依次添加到概率集合中,則構造的數軸為:010范圍內表示概率10,1030范圍內表示概率為20,3060范圍內表示概率為30,數軸上的長度對應着相應的概率。由這種處理方式可知,概率總和並不需要等於1。該工具類的成功與否在於Random.nextDouble()能否等概率地生成01之間的任意一個數。
對該抽獎工具進行測試,測試類如下:

package com.ruoyi.project.dy.utils;


/**
 * @description:
 */
public class Result {
    private int index;
    private int sumTime;
    private int time;
    private double probability;
    private double realProbability;

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public int getTime() {
        return time;
    }

    public void setTime(int time) {
        this.time = time;
    }

    public int getSumTime() {
        return sumTime;
    }

    public void setSumTime(int sumTime) {
        this.sumTime = sumTime;
    }

    public double getProbability() {
        return probability;
    }

    public double getRealProbability() {
        return realProbability;
    }

    public void setRealProbability(double realProbability) {
        this.realProbability = realProbability;
    }

    public Result(){

    }

    public Result(int index, int sumTime, int time, double realProbability) {
        this.setIndex(index);
        this.setTime(time);
        this.setSumTime(sumTime);
        this.setRealProbability(realProbability);

    }

    @Override
    public String toString(){
        return "索引值:" + index + ",抽獎總數:" + sumTime + ",抽中次數:" + time + ",概率:"
                + realProbability + ",實際概率:" + (double)time/sumTime;
    }
}
//----------------------------------

package com.ruoyi.project.dy.utils;

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

/**
 * @description: 測試抽獎工具
 */
public class TestLottery {
    static final int TIME = 1000000;

    public static void iteratorMap(Map<Integer, Integer> map, List<Double> list){
        for(Map.Entry<Integer, Integer> entry : map.entrySet()){
            int index = entry.getKey();
            int time  = entry.getValue();
            Result result = new Result(index, TIME, time, list.get(index));
            System.out.println(result);
        }
    }

    public static void main(String[] args) {
        //構造概率集合
        List<Double> list = new ArrayList<Double>();
        list.add(90d);
        list.add(4d);
        list.add(3d);
        list.add(2d);
        list.add(1d);
        LotteryUtil ll = new LotteryUtil(list);
        double sumProbability = ll.getMaxElement();

        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for(int i = 0; i < TIME; i++){
            int index = ll.randomColunmIndex();
            if(map.containsKey(index)){
                map.put(index, map.get(index) + 1);
            }else{
                map.put(index, 1);
            }
        }
        for(int i = 0; i < list.size(); i++){
            double probability = list.get(i) / sumProbability;
            list.set(i, probability);
        }
        iteratorMap(map, list);

    }
}

調用方式

public LotteryUtil(List<Double> list)

傳入參數作為概率集合

public int randomColunmIndex()

進行抽獎操作,返回List集合中索引下標

測試結果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM