1. 程式人生 > >簡單的抽獎系統實現

簡單的抽獎系統實現

需求|原因
朋友突然給我一個抽獎的一個需求,讓我幫他他分析下,需求大致是這樣的。
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++; } } }