前言
之前购买彩票时很少中奖,实际上彩票的中奖概率非常低。在多次尝试后,只中过一次。考虑到中奖机会有限,我决定尝试实现一个彩票自动购买程序,类似于机选功能。这样,我可以更加灵活地进行尝试,而不受实际彩票中奖概率的限制。
代码实现
package demo.game;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import java.util.*;
/**
* @author jisl on 2023/7/31 15:52
* 双色球彩票
*/
public class DoubleColorBallLottery {
// 彩票期数
private int lotteryNumber = 0;
// 开奖号码
private Set<Integer> winRedNum = new HashSet<>();
private int winBlueNum;
// 用户购买的彩票
private final List<List<Integer>> userLottery = new ArrayList<>();
// 用户中奖的彩票
private final Map<Integer, List<String>> userPrizeLottery = new HashMap<>();
public int[] lotteryAmount = new int[]{0, 5000000, 1250000, 3000, 200, 10, 5};
private static final int MAX_PRIZE_LEVEL = 6;
Random random = new Random();
/**
* 彩票开奖
*
* @author jisl on 2023/7/31 16:06
**/
public void lotteryDrawing() {
winRedNum = buildRedNum();
winBlueNum = buildBlueNum();
System.out.printf("[第%s期双色球]开奖结果:红球:%s,蓝球:%s%n", lotteryNumber, JSON.toJSONString(winRedNum), winBlueNum);
}
private int buildBlueNum() {
return random.nextInt(16) + 1;
}
private HashSet<Integer> buildRedNum() {
final HashSet<Integer> set = new HashSet<>();
while (set.size() < 6) {
final int randomNum = random.nextInt(33) + 1;
set.add(randomNum);
}
return set;
}
/**
* 买彩票
*
* @author jisl on 2023/7/31 16:07
**/
public void buy(int count) {
lotteryNumber = RandomUtil.randomInt(999);
for (int i = 0; i < count; i++) {
final ArrayList<Integer> lottery = new ArrayList<>(buildRedNum());
lottery.add(buildBlueNum());
userLottery.add(lottery);
}
}
public void redemption() {
// 一到六等奖
for (int i = 1; i <= MAX_PRIZE_LEVEL; i++) {
userPrizeLottery.put(i, new ArrayList<>());
}
for (List<Integer> lottery : userLottery) {
int readBallMatches = countMatchingNumbers(lottery);
boolean blueBallMatch = lottery.get(6) == winBlueNum;
int prizeItem = calculatePrize(readBallMatches, blueBallMatch);
if (prizeItem != 0) {
// 中奖了
final List<String> numbers = userPrizeLottery.get(prizeItem);
numbers.add(JSON.toJSONString(lottery));
}
}
System.out.println(String.format("[第%s期双色球]中奖结果:", lotteryNumber));
int userPrizeCount = 0;
int userPrizeAmount = 0;
for (int i = 1; i <= MAX_PRIZE_LEVEL; i++) {
final int userPrizeItemCount = userPrizeLottery.get(i).size();
userPrizeCount += userPrizeItemCount;
userPrizeAmount += lotteryAmount[i] * userPrizeItemCount;
if (i <= 3) {
System.out.println(String.format("%s等奖中奖个数:%s,中奖号码:%s", i, userPrizeItemCount, userPrizeLottery.get(i)));
} else {
System.out.println(String.format("%s等奖中奖个数:%s,中奖号码:-", i, userPrizeItemCount));
}
}
// 共计中奖率:6.71%
System.out.println(String.format("一共买了[%s张]彩票,中奖个数=%s,中奖概率=%s;购买彩票费用=%s,奖金=%s,盈利=%s"
, userLottery.size(), userPrizeCount, 1.0 * userPrizeCount / userLottery.size(), userLottery.size() * 2, userPrizeAmount, userPrizeAmount - userLottery.size() * 2));
}
private int calculatePrize(int readBallMatches, boolean blueBallMatch) {
if (readBallMatches == 6 && blueBallMatch) {
return 1;
} else if (readBallMatches == 6) {
return 2;
} else if (readBallMatches == 5 && blueBallMatch) {
return 3;
} else if (readBallMatches == 5 || (readBallMatches == 4 && blueBallMatch)) {
return 4;
} else if (readBallMatches == 4 || (readBallMatches == 3 && blueBallMatch)) {
return 5;
} else if (blueBallMatch) {
return 6;
}
return 0;
}
private int countMatchingNumbers(List<Integer> lottery) {
int count = 0;
for (int i = 0; i < 6; i++) {
if (winRedNum.contains(lottery.get(i))) {
count += 1;
}
}
return count;
}
public void game(int n) {
buy(n);
lotteryDrawing();
redemption();
}
public static void main(String[] args) {
final DoubleColorBallLottery lottery = new DoubleColorBallLottery();
lottery.game(100000);
}
}
执行效果
[第88期双色球]开奖结果:红球:[2,3,19,23,13,29],蓝球:15
[第88期双色球]中奖结果:
1等奖中奖个数:0,中奖号码:[]
2等奖中奖个数:0,中奖号码:[]
3等奖中奖个数:0,中奖号码:[]
4等奖中奖个数:43,中奖号码:-
5等奖中奖个数:752,中奖号码:-
6等奖中奖个数:5957,中奖号码:-
一共买了[100000张]彩票,中奖个数=6752,中奖概率=0.06752;购买彩票费用=200000,奖金=45905,盈利=-154095
概率计算
一等奖(6+1)中奖概率为:
红球33选6乘以蓝球16选1= C ( 33 , 6 ) × 16 C(33,6)\times16 C(33,6)×16= 33 ! 6 ! × ( 33 − 6 ) ! × 16 \frac{ 33!} {6!\times(33-6)!}\times16 6!×(33−6)!33!×16= 1 17721088 \frac{1} {17721088} 177210881
二等奖(6+0)中奖概率为:
红球33选6乘以蓝球16选15(红色都中了,蓝色没中是 15 16 \frac{15} {16} 1615)= 15 17721088 \frac {15} {17721088} 1772108815
三等奖(5+1)中奖概率为:
红球33选5乘以蓝球16选1(红色剩下27个数字可以选没中,任意一个球)= 27 × 6 17721088 \frac {27\times6} {17721088} 1772108827×6= 162 17721088 \frac{162}{17721088} 17721088162
四等奖(5+0、4+1)中奖概率为:
红球33选5乘以蓝球16选15+红球33选4乘以蓝球16选1= 27 × 6 × 15 + 6 × 5 ÷ 2 × 27 × 26 ÷ 2 27\times6\times15+6\times5\div2\times27\times26\div2 27×6×15+6×5÷2×27×26÷2= 7695 17721088 \frac{7695} {17721088} 177210887695 (4+1,从27个数可以随机选出两个数,选出的两个数和顺序无关)
五等奖(4+0、3+1)中奖概率为:
红球33选4乘以蓝球16选15+红球33选3乘以蓝球16选1= 27 × 26 ÷ 2 × 6 × 5 ÷ 2 × 15 + 6 × 5 × 4 ÷ 6 × 27 × 26 × 25 ÷ 6 27\times26\div2\times6\times5\div2\times15+6\times5\times4\div6\times27\times26\times25\div6 27×26÷2×6×5÷2×15+6×5×4÷6×27×26×25÷6= 137475 17721088 \frac{137475}{17721088} 17721088137475
六等奖(2+1、1+1、0+1)中奖概率为:
红球33选0乘以蓝球16选1=
6
×
5
×
4
×
3
÷
(
4
×
3
×
2
)
×
27
×
26
×
25
×
24
÷
(
4
×
3
×
2
)
+
6
×
5
×
4
×
3
×
2
÷
(
5
×
4
×
3
×
2
)
×
27
×
26
×
25
×
24
×
23
÷
(
5
×
4
×
3
×
2
)
+
6
×
5
×
4
×
3
×
2
×
1
/
(
6
×
5
×
4
×
3
×
2
)
×
27
×
26
×
2
×
24
×
23
×
22
÷
(
6
×
5
×
4
×
3
×
2
)
6\times5\times4\times3\div(4\times3\times2)\times27\times26\times25\times24\div(4\times3\times2)+6\times5\times4\times3\times2\div(5\times4\times3\times2)\times27\times26\times25\times24\times23\div(5\times4\times3\times2)+6\times5\times4\times3\times2\times1/(6\times5\times4\times3\times2)\times27\times26\times2\times24\times23\times22\div(6\times5\times4\times3\times2)
6×5×4×3÷(4×3×2)×27×26×25×24÷(4×3×2)+6×5×4×3×2÷(5×4×3×2)×27×26×25×24×23÷(5×4×3×2)+6×5×4×3×2×1/(6×5×4×3×2)×27×26×2×24×23×22÷(6×5×4×3×2)=
1043640
17721088
\frac{1043640}{17721088}
177210881043640
买了所有的彩票17721088组合,花费17721088*2=35442176=3500万,一共中奖金额=
1043640
×
5
+
137475
×
10
+
7695
×
200
+
162
×
3000
+
15
×
5
×
1
0
6
+
5
×
1
0
6
1043640\times5+137475\times10+7695\times200+162\times3000+15\times5\times10^6+5\times10^6
1043640×5+137475×10+7695×200+162×3000+15×5×106+5×106=88617950。共计中奖率:6.71%