1. 程式人生 > >多件商品根據概率抽獎

多件商品根據概率抽獎

size 最大 clas implement 模塊 wid ood pri type

  最近在項目中分配了一個抽獎模塊的任務,這裏先說一下需求把:每個抽獎活動後臺會配置多個中獎獎品,分為特殊獎品和普通獎品,所有獎品的中獎概率之和加起來為1。用戶端用戶抽獎需要根據概率來隨機抽中一個商品。開始我腦子生出來的第一想法是生成一個隨機數,然後讓這個隨機數跟概率去比較,取小於這個隨機數的最大一個概率對應的商品為中獎商品,後來一想,發現自己想的太簡單直觀了,這樣抽中的商品中獎概率不滿足配置的中獎概率。在網上搜了一下相關的問題,然後就弄清楚了。說來慚愧,這麽一個簡單的算法題,自己竟然第一時間沒有沒有想到。所以在這裏把這個問題記錄下來。

public class DrawGoodsDO implements
Comparable<DrawGoodsDO>{ //主鍵id private long id; //抽獎id private long drawId; //商品名稱 private String goodsName; //商品圖片地址 private String goodsImageUrl; //上架庫存 private int drawStock; //當前庫存 private int drawStockCur; //商品類型,1特殊商品,2普通商品 private int goodsType;
// 中獎概率 private double drawRate; // 添加時間 private Timestamp addTime; //商品圖片地址,絕對路徑 private String goodsImageUrlFormat; /** * 商品圖片地址,絕對路徑 * * @return GoodsImageUrlFormat the GoodsImageUrlFormat */ public String getGoodsImageUrlFormat() { return goodsImageUrlFormat; }
/** * 商品圖片地址,絕對路徑 * * @param goodsImageUrlFormat the goodsImageUrlFormat to set */ public void setGoodsImageUrlFormat(String goodsImageUrlFormat) { this.goodsImageUrlFormat = goodsImageUrlFormat; } //主鍵id public long getId() { return this.id; } //主鍵id public void setId(long id) { this.id = id; } //抽獎id public long getDrawId() { return this.drawId; } //抽獎id public void setDrawId(long drawId) { this.drawId = drawId; } //商品名稱 public String getGoodsName() { return this.goodsName; } //商品名稱 public void setGoodsName(String goodsName) { this.goodsName = goodsName; } //商品圖片地址 public String getGoodsImageUrl() { return this.goodsImageUrl; } //商品圖片地址 public void setGoodsImageUrl(String goodsImageUrl) { if (goodsImageUrl != null) { setGoodsImageUrlFormat(FileUrlConfig.file_visit_url + goodsImageUrl); } this.goodsImageUrl = goodsImageUrl; } //上架庫存 public int getDrawStock() { return this.drawStock; } //上架庫存 public void setDrawStock(int drawStock) { this.drawStock = drawStock; } //當前庫存 public int getDrawStockCur() { return this.drawStockCur; } //當前庫存 public void setDrawStockCur(int drawStockCur) { this.drawStockCur = drawStockCur; } //商品類型,1特殊商品,2普通商品 public int getGoodsType() { return this.goodsType; } //商品類型,1特殊商品,2普通商品 public void setGoodsType(int goodsType) { this.goodsType = goodsType; } // 獲取 中獎概率 public double getDrawRate() { return this.drawRate; } // 設置 中獎概率 public void setDrawRate(double drawRate) { this.drawRate = drawRate; } // 獲取 添加時間 public Timestamp getAddTime() { return this.addTime; } // 設置 添加時間 public void setAddTime(Timestamp addTime) { this.addTime = addTime; } @Override public int compareTo(DrawGoodsDO drawGoods) { if (this.drawRate >= drawGoods.getDrawRate()) { return 1; } return -1; } }

這個是抽獎獎品實體類,他實現了Comparable接口,實現了compareTo()方法,這個方法很重要,後面再說。

/**
     * 從抽獎獎品列表中隨機抽中一個
     *
     * @param drawGoodsList 獎品列表
     * @return
     */
    private DrawGoodsDO randomGetDrawGoods(List<DrawGoodsDO> drawGoodsList) {
        if (ValidateUtil.isNull(drawGoodsList)) {
            return null;
        }
        //將獎品按概率從小到大排序
        Collections.sort(drawGoodsList);
        //求出總概率
        double sumRate = 0D;
        for (DrawGoodsDO drawGoodsDO : drawGoodsList) {
            sumRate += drawGoodsDO.getDrawRate();
        }
        if (sumRate != 100) {
            //如果總概率之和不為100,重新計算他們的概率,讓他們的概率和為100
            for (DrawGoodsDO drawGoodsDO : drawGoodsList) {
                drawGoodsDO.setDrawRate(drawGoodsDO.getDrawRate() * 100 / sumRate);
            }
        }

        //將每個獎品中獎區間段保存到list裏面
        List<Double> list = new ArrayList<>();
        double rate = 0D;
        for (DrawGoodsDO drawGoodsDO : drawGoodsList) {
            rate += drawGoodsDO.getDrawRate() / sumRate;
            list.add(rate);
        }
        //找出符合概率得獎品所占的索引位置
        int index = 0;
        double randomNum = Math.random();
        for (int i=0;i<list.size();i++) {
            if (randomNum > list.get(i)) {
                index = i + 1;
            }
        }
        return drawGoodsList.get(index);
    }

上面就是主要的實現方法,這裏最重要的就是先將獎品列表按照概率從小到大排序,因為Collections.sort()方法需要列表元素實現Comparable接口。所以上面的實體類中才那樣寫。然後根據中獎概率算出中獎區間段並且保存到list中,最後在生成一個隨機數與這個中間區間段的list來比較,最後選中獎品。

多件商品根據概率抽獎