中獎率 1%,每人抽 10 次,也就是說 10 個人就可以抽 100 次,概率上來說 10 個人必中獎?假設邏輯是這樣的,可以這樣設計:
專注于為中小企業(yè)提供網(wǎng)站設計制作、做網(wǎng)站服務,電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業(yè)農(nóng)安免費做網(wǎng)站提供優(yōu)質(zhì)的服務。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了1000多家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設實現(xiàn)規(guī)模擴充和轉(zhuǎn)變。
1、先寫定義一個表示概率的數(shù)組 ratio,這個數(shù)組最多可以存 100 個數(shù)字,每個數(shù)字的值不能重復,范圍是 0 到 100,表示 100%?,F(xiàn)在你的中獎率是 1%,那么就存一個數(shù)字。
2、定義一個是否中將的布爾型變量 win;
每次抽獎用隨機正整數(shù)對 100 取余,再將結果拿到 ratio 數(shù)組中查找,如果找到就將 win 賦值為 true,表示中獎。如果沒找到就對 win 賦值為 false,表示沒有中獎。
import?java.awt.EventQueue;
import?java.awt.TextArea;
import?java.awt.TextField;
import?java.awt.event.ActionEvent;
import?java.awt.event.ActionListener;
import?java.util.Random;
import?javax.swing.JButton;
import?javax.swing.JFrame;
import?javax.swing.JLabel;
import?javax.swing.JPanel;
import?javax.swing.JTextArea;
import?javax.swing.JTextField;
import?javax.swing.border.EmptyBorder;
public?class?LuckySelect?extends?JFrame?{
private?JPanel?contentPane;
private?JTextField?textFieldA;
private?JTextField?textFieldB;
private?JTextField?textFieldC;
private?TextField?textField;
private?JTextField?textFieldResult;
private?JTextArea?textArea;
/**
?*?Launch?the?application.
?*/
public?static?void?main(String[]?args)?{
EventQueue.invokeLater(new?Runnable()?{
public?void?run()?{
try?{
LuckySelect?frame?=?new?LuckySelect();
frame.setVisible(true);
}?catch?(Exception?e)?{
e.printStackTrace();
}
}
});
}
/**
?*?Create?the?frame.
?*/
public?LuckySelect()?{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100,?100,?450,?251);
contentPane?=?new?JPanel();
contentPane.setBorder(new?EmptyBorder(5,?5,?5,?5));
contentPane.setLayout(null);
setContentPane(contentPane);
JLabel?lblA?=?new?JLabel("A");
lblA.setBounds(10,?128,?54,?15);
contentPane.add(lblA);
JLabel?lblB?=?new?JLabel("B");
lblB.setBounds(124,?128,?54,?15);
contentPane.add(lblB);
JLabel?lblC?=?new?JLabel("C");
lblC.setBounds(254,?128,?54,?15);
contentPane.add(lblC);
textFieldA?=?new?JTextField();
textFieldA.setBounds(30,?125,?66,?21);
contentPane.add(textFieldA);
textFieldA.setColumns(10);
textFieldB?=?new?JTextField();
textFieldB.setColumns(10);
textFieldB.setBounds(149,?125,?66,?21);
contentPane.add(textFieldB);
textFieldC?=?new?JTextField();
textFieldC.setColumns(10);
textFieldC.setBounds(264,?125,?66,?21);
contentPane.add(textFieldC);
textField?=?new?TextField();
textField.setBounds(98,?167,?157,?21);
contentPane.add(textField);
textField.setColumns(10);
textFieldResult?=?new?JTextField();
textFieldResult.setBounds(280,?167,?66,?21);
contentPane.add(textFieldResult);
textFieldResult.setColumns(10);
textFieldA.setText("10");
textFieldB.setText("10");
textFieldC.setText("10");
JButton?button?=?new?JButton("\u62BD\u5956");
button.addActionListener(new?ActionListener()?{
public?void?actionPerformed(ActionEvent?e)?{
select();
}
});
button.setBounds(0,?166,?93,?23);
contentPane.add(button);
textArea?=?new?JTextArea();
textArea.setBounds(30,?31,?306,?83);
contentPane.add(textArea);
}
protected?void?select()?{
//?TODO?Auto-generated?method?stub
int?aNum?=?Integer.decode(textFieldA.getText());
int?bNum?=?Integer.decode(textFieldB.getText());
int?cNum?=?Integer.decode(textFieldB.getText());
Random?r?=?new?Random();
int?random?=?r.nextInt(aNum?+?bNum?+?cNum);
if(random?=?aNum){
textFieldA.setText(Integer.toString(Integer.decode(textFieldA.getText())?-?1));
textArea.append(Integer.toString(random)?+?"抽中了A\n");
}else?if(random?=?aNum?+?bNum){
textFieldB.setText(Integer.toString(Integer.decode(textFieldB.getText())?-?1));
textArea.append(Integer.toString(random)?+?"抽中了B\n");
}else?if(random?=?aNum?+?bNum?+?cNum){
textFieldC.setText(Integer.toString(Integer.decode(textFieldC.getText())?-?1));
textArea.append(Integer.toString(random)?+?"抽中了C\n");
}
}
}
import?java.util.ArrayList;
import?java.util.List;
import?java.util.Random;
/**
*?抽獎工具類,概率和可以不等于1
*?概率為百分數(shù)去掉百分號的部分,如10%,則為10
*?抽獎操作如下:
*?1.輸入抽獎概率集合,【抽獎概率集合為{10.0,?20.0,?30.0}】
*?2.生成連續(xù)集合,???????【生成的連續(xù)集合為{(0.0,?10.0],(10.0,?30.0],(30.0,?60.0]}】
*?3.生成隨機數(shù),??????????【生成方法為?random.nextDouble()?*?maxElement】
*?4.判斷隨機數(shù)在哪個區(qū)間內(nèi),返回該區(qū)間的index【生成了隨機數(shù)12.001,則它屬于(10.0,?30.0],返回?index?=?1】
*
*/
public?class?LotteryUtil?{
/**
*?定義一個連續(xù)集合
*?集合中元素x滿足:(minElement,maxElement]
*?數(shù)學表達式為:minElement??x?=?maxElement
*
*/
public?class?ContinuousList?{
private?double?minElement;
private?double?maxElement;
public?ContinuousList(double?minElement,?double?maxElement){
if(minElement??maxElement){
throw?new?IllegalArgumentException("區(qū)間不合理,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?ListContinuousList?lotteryList;???//概率連續(xù)集合
private?double?maxElement;??????????????????//這里只需要最大值,最小值默認為0.0
/**
*?構造抽獎集合
*?@param?list?為獎品的概率
*/
public?LotteryUtil(ListDouble?list){
lotteryList?=?new?ArrayListContinuousList();
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間的隨機數(shù)
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?ListContinuousList?getLotteryList()?{
return?lotteryList;
}
public?void?setLotteryList(ListContinuousList?lotteryList)?{
this.lotteryList?=?lotteryList;
}
}
該工具類的基本思想是,將抽獎概率分布到數(shù)軸上,如現(xiàn)有三個抽獎概率10、20、30,將三者依次添加到概率集合中,則構造的數(shù)軸為:0~10范圍內(nèi)表示概率10,10~30范圍內(nèi)表示概率為20,30~60范圍內(nèi)表示概率為30,數(shù)軸上的長度對應著相應的概率。由這種處理方式可知,概率總和并不需要等于1。該工具類的成功與否在于Random.nextDouble()能否等概率地生成0~1之間的任意一個數(shù)。
對該抽獎工具進行測試,測試類如下:
[java]?view plain?copy
package?com.lottery;
import?java.util.ArrayList;
import?java.util.HashMap;
import?java.util.List;
import?java.util.Map;
import?java.util.Map.Entry;
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);
}
public?String?toString(){
return?"索引值:"?+?index?+?",抽獎總數(shù):"?+?sumTime?+?",抽中次數(shù):"?+?time?+?",概率:"
+?realProbability?+?",實際概率:"?+?(double)time/sumTime;
}
}
public?class?TestLottery?{
static?final?int?TIME?=?100000;
public?static?void?iteratorMap(MapInteger,?Integer?map,?ListDouble?list){
for(EntryInteger,?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)?{
//構造概率集合
ListDouble?list?=?new?ArrayListDouble();
list.add(20d);
list.add(80d);
list.add(50d);
list.add(30d);
LotteryUtil?ll?=?new?LotteryUtil(list);
double?sumProbability?=?ll.getMaxElement();
MapInteger,?Integer?map?=?new?HashMapInteger,?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);
}
}
運行結果:
由結果可知,抽獎100000時, 得到的實際概率基本與正式概率相當。
以下說明此類調(diào)用方式:
[java]?view plain?copy
public?LotteryUtil(ListDouble?list)
說明:構造方法,傳入?yún)?shù)為一個概率集合
[java]?view plain?copy
public?int?randomColunmIndex()
功能:進行抽獎操作,返回List集合的索引下標,此下標對應的概率的獎品即為抽中的獎品
優(yōu)先級規(guī)則使高等獎盡量在后期抽出
import?java.util.LinkedList;
import?java.util.List;
public?class?GetGift?{
//?獎品倉庫
private?ListGift?gifts?=?new?LinkedListGift();
public?GetGift()?{
//?生成一堆獎品放進獎品倉庫
//?一等獎一個優(yōu)先級1,二等獎兩個優(yōu)先級2。。。20等獎20個優(yōu)先級20
for?(int?i?=?1;?i?=?20;?i++)?{
GiftType?gt?=?new?GiftType(i?+?"等獎",?i,?i);
for?(int?j?=?1;?j?=?i;?j++)?{
gifts.add(new?Gift(i?+?"等獎——第"?+?j?+?"號",?gt));
}
}
}
//?抽獎
public?synchronized?Gift?getGift()?{
int?randomNumber?=?(int)?(Math.random()?*?total());
int?priority?=?0;
for?(Gift?g?:?gifts)?{
priority?+=?g.getType().getPriority();
if?(priority?=?randomNumber)?{
//?從獎品庫移出獎品
gifts.remove(g);
return?g;
}
}
//?抽獎次數(shù)多于獎品時,沒有獎品
return?null;
}
/**
?*?@param?args
?*/
public?static?void?main(String[]?args)?{
GetGift?gg?=?new?GetGift();
//?一共生成210個獎品,抽210次,多抽顯示null
for?(int?i?=?0;?i??210;?i++)?{
System.out.println(gg.getGift());
}
}
//?計算總優(yōu)先級,內(nèi)部使用
private?int?total()?{
int?result?=?0;
for?(Gift?g?:?gifts)?{
result?+=?g.getType().getPriority();
}
return?result;
}
}
//?記錄獎品的信息
//?如1等獎共1個,優(yōu)先級為1最難抽
class?GiftType?{
//?名字(如1等獎)
private?String?name;
//?這種獎品的數(shù)量,數(shù)量越大越容易抽到
private?int?quantity;
//?這種獎品的優(yōu)先級,最小為1,數(shù)越大越容易抽到
private?int?priority;
public?GiftType(String?name,?int?quantity,?int?priority)?{
this.name?=?name;
this.quantity?=?quantity;
this.priority?=?priority;
}
public?int?getPriority()?{
return?priority;
}
@Override
public?String?toString()?{
return?"GiftType?[name="?+?name?+?",?quantity="?+?quantity?+?",?priority="?+?priority?+?"]";
}
}
//?獎品
class?Gift?{
//?每個獎品有唯一id,抽獎不會重復,格式為"16等獎——第8號"
private?String?id;
//?這個獎品的類別
private?GiftType?type;
public?Gift(String?id,?GiftType?type)?{
this.id?=?id;
this.type?=?type;
}
public?GiftType?getType()?{
return?type;
}
@Override
public?String?toString()?{
return?"Gift?[id="?+?id?+?",?type="?+?type?+?"]";
}
}
抽取問題, 重點是 同一個學號不能重復被抽取.
解決辦法很多,
比如數(shù)組可以使用下標來標記,號碼是否被使用,使用了就繼續(xù)下一次抽取
也可以使用集合來抽取,把集合順序打亂,然后隨便抽幾個就可以了
參考代碼:數(shù)組法
import?java.util.Random;
public?class?Test?{
public?static?void?main(String[]?args)?{
int?stuNums=30;
int[]?nums=new?int[stuNums];//存儲學號的數(shù)組
boolean[]?flags=new?boolean[stuNums];//標記,用于標記對應下標的學號是否已經(jīng)被抽取過了
for?(int?i?=?0;?i??stuNums;?i++)?{
nums[i]=i+1;//給學號賦值
}
Random?r=new?Random();
while(true){
int?index?=?r.nextInt(stuNums);
if(!flags[index]){
System.out.println("A等:"+nums[index]);
flags[index]=true;?//標記已經(jīng)被使用過了
break;
}
}
for?(int?i?=?0;?i??2;?i++)?{
int?index?=?r.nextInt(stuNums);
if(!flags[index]){
System.out.println("B等:"+nums[index]);
flags[index]=true;
}else{
i--;//如果已經(jīng)被抽取過了?,那么i建議,再次循環(huán)
}
}
for?(int?i?=?0;?i??3;?i++)?{
int?index?=?r.nextInt(stuNums);
if(!flags[index]){
System.out.println("c等:"+nums[index]);
flags[index]=true;
}else{
i--;
}
}
}
}
集合法
import?java.util.ArrayList;
import?java.util.Collections;
public?class?Test2?{
public?static?void?main(String[]?args)?{
int?stuNums=20;
ArrayListInteger?list=new?ArrayListInteger();
for?(int?i?=?0;?i??stuNums;?i++)?{
list.add(i+1);
}
System.out.println("有序"+list);
Collections.shuffle(list);//打亂順序
System.out.println("亂序"+list);
System.out.println("A等"+list.get(0));
System.out.println("B等"+list.get(1));
System.out.println("B等"+list.get(2));
System.out.println("C等"+list.get(3));
System.out.println("C等"+list.get(4));
System.out.println("C等"+list.get(5));
}
}
public class Lottery {
private int m = 1000;//發(fā)放獎券的數(shù)量
private int n = 2;//獎品的數(shù)量
public boolean getLottery(){
boolean isLottery = false;
double d = (double)n/(double)m;//中獎概率
double r = Math.random();//0~1之間的隨機數(shù),包括0
if(rd){//如果隨機數(shù)小于概率 那么中獎
n--;//獎品數(shù)量-1
isLottery = true;
}
m--;//獎券數(shù)量-1
return isLottery;
}
}