HARMONYOS应用实例269:彩票中奖概率分析
·
- 彩票中奖概率分析
- 功能:模拟双色球等彩票规则,计算中奖概率,体验“小概率事件”的不可能性。
模拟双色球等彩票规则(6红+1蓝)
显示各奖项的中奖概率
随机选号功能
模拟开奖功能(10万次模拟)
记录中奖情况
体验"小概率事件"的不可能性
显示总组合数(17,721,088种)
显示各奖项中奖条件和概率
// 彩票中奖概率分析
// 功能:模拟双色球等彩票规则,计算中奖概率,体验"小概率事件"的不可能性
// 彩票类型配置接口
interface LotteryConfig {
name: string;
redBallCount: number;
redBallRange: number;
blueBallCount: number;
blueBallRange: number;
totalCombinations: number;
}
// 中奖等级接口
interface PrizeLevel {
level: number;
name: string;
redMatch: number;
blueMatch: number;
probability: string;
description: string;
}
// 球号接口
interface BallNumbers {
red: number[];
blue: number[];
}
@Entry
@Component
struct LotteryProbability {
@State currentLottery: LotteryConfig = {
name: '双色球',
redBallCount: 6,
redBallRange: 33,
blueBallCount: 1,
blueBallRange: 16,
totalCombinations: 17721088
};
@State prizeLevels: PrizeLevel[] = [];
@State selectedRed: number[] = [];
@State selectedBlue: number[] = [];
@State isSimulating: boolean = false;
@State simulationCount: number = 0;
@State wins: Map<number, number> = new Map<number, number>();
aboutToAppear() {
this.calculatePrizeLevels()
this.generateRandomNumbers()
}
private calculatePrizeLevels() {
const lottery = this.currentLottery
this.prizeLevels = [
{
level: 1,
name: '一等奖',
redMatch: 6,
blueMatch: 1,
probability: this.formatProbability(1 / lottery.totalCombinations),
description: '6红+1蓝,中大奖!'
},
{
level: 2,
name: '二等奖',
redMatch: 6,
blueMatch: 0,
probability: this.formatProbability(15 / lottery.totalCombinations),
description: '6红+0蓝'
},
{
level: 3,
name: '三等奖',
redMatch: 5,
blueMatch: 1,
probability: this.formatProbability(162 / lottery.totalCombinations),
description: '5红+1蓝'
},
{
level: 4,
name: '四等奖',
redMatch: 5,
blueMatch: 0,
probability: this.formatProbability(2430 / lottery.totalCombinations),
description: '5红+0蓝 或 4红+1蓝'
},
{
level: 5,
name: '五等奖',
redMatch: 4,
blueMatch: 0,
probability: this.formatProbability(12960 / lottery.totalCombinations),
description: '4红+0蓝 或 3红+1蓝'
},
{
level: 6,
name: '六等奖',
redMatch: 2,
blueMatch: 1,
probability: this.formatProbability(137475 / lottery.totalCombinations),
description: '2红+1蓝 或 1红+1蓝 或 0红+1蓝'
}
]
}
private formatProbability(prob: number): string {
if (prob < 0.0001) {
return prob.toExponential(4)
}
return prob.toFixed(6)
}
private combination(n: number, k: number): number {
if (k === 0 || k === n) return 1
if (k > n - k) k = n - k
let result = 1
for (let i = 1; i <= k; i++) {
result = result * (n - k + i) / i
}
return result
}
private generateRandomNumbers() {
this.selectedRed = []
this.selectedBlue = []
while (this.selectedRed.length < this.currentLottery.redBallCount) {
const num = Math.floor(Math.random() * this.currentLottery.redBallRange) + 1
if (!this.selectedRed.includes(num)) {
this.selectedRed.push(num)
}
}
this.selectedRed.sort((a, b) => a - b)
while (this.selectedBlue.length < this.currentLottery.blueBallCount) {
const num = Math.floor(Math.random() * this.currentLottery.blueBallRange) + 1
if (!this.selectedBlue.includes(num)) {
this.selectedBlue.push(num)
}
}
}
private generateWinningNumbers(): BallNumbers {
const red: number[] = []
const blue: number[] = []
while (red.length < this.currentLottery.redBallCount) {
const num = Math.floor(Math.random() * this.currentLottery.redBallRange) + 1
if (!red.includes(num)) {
red.push(num)
}
}
red.sort((a, b) => a - b)
while (blue.length < this.currentLottery.blueBallCount) {
const num = Math.floor(Math.random() * this.currentLottery.blueBallRange) + 1
if (!blue.includes(num)) {
blue.push(num)
}
}
const result: BallNumbers = { red, blue }
return result
}
private checkWin(winning: BallNumbers, selected: BallNumbers): number {
let redMatch = 0
selected.red.forEach((num) => {
if (winning.red.includes(num)) {
redMatch++
}
})
let blueMatch = 0
selected.blue.forEach((num) => {
if (winning.blue.includes(num)) {
blueMatch++
}
})
if (redMatch === 6 && blueMatch === 1) return 1
if (redMatch === 6 && blueMatch === 0) return 2
if (redMatch === 5 && blueMatch === 1) return 3
if ((redMatch === 5 && blueMatch === 0) || (redMatch === 4 && blueMatch === 1)) return 4
if ((redMatch === 4 && blueMatch === 0) || (redMatch === 3 && blueMatch === 1)) return 5
if ((redMatch === 2 && blueMatch === 1) || (redMatch === 1 && blueMatch === 1) || (redMatch === 0 && blueMatch === 1)) return 6
return 0
}
private getWinCount(level: number): number {
return this.wins.get(level) || 0
}
private hasWin(level: number): boolean {
const count = this.getWinCount(level)
return count > 0
}
private startSimulation() {
this.isSimulating = true
this.simulationCount = 0
this.wins.clear()
const interval = setInterval(() => {
if (this.simulationCount >= 100000) {
clearInterval(interval)
this.isSimulating = false
return
}
for (let i = 0; i < 1000; i++) {
const winning = this.generateWinningNumbers()
const prizeLevel = this.checkWin(winning, { red: this.selectedRed, blue: this.selectedBlue })
if (prizeLevel > 0) {
const currentCount = this.wins.get(prizeLevel) || 0
this.wins.set(prizeLevel, currentCount + 1)
}
}
this.simulationCount += 1000
}, 10)
}
private reset() {
this.isSimulating = false
this.simulationCount = 0
this.wins.clear()
this.generateRandomNumbers()
}
build() {
Column({ space: 15 }) {
Text('彩票中奖概率分析')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.fontColor('#E91E63')
.margin({ top: 10 })
Text('模拟双色球等彩票规则,计算中奖概率,体验"小概率事件"的不可能性')
.fontSize(14)
.fontColor('#666')
.textAlign(TextAlign.Center)
.padding({ left: 15, right: 15 })
Scroll() {
Column({ space: 15 }) {
Column({ space: 10 }) {
Text('彩票类型')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333')
.width('100%')
Text(this.currentLottery.name)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#E91E63')
.width('100%')
Column({ space: 5 }) {
Text(`规则:从${this.currentLottery.redBallRange}个红球中选${this.currentLottery.redBallCount}个,从${this.currentLottery.blueBallRange}个蓝球中选${this.currentLottery.blueBallCount}个`)
.fontSize(12)
.fontColor('#666')
.width('100%')
Text(`总组合数:${this.currentLottery.totalCombinations.toLocaleString()} 种`)
.fontSize(14)
.fontColor('#E91E63')
.fontWeight(FontWeight.Bold)
.width('100%')
}
.width('100%')
.padding(10)
.backgroundColor('#FCE4EC')
.borderRadius(8)
}
.width('100%')
.padding(15)
.backgroundColor('#FAFAFA')
.borderRadius(10)
Column({ space: 10 }) {
Text('您选的号码')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333')
.width('100%')
Column({ space: 10 }) {
Text('红球:')
.fontSize(14)
.fontColor('#F44336')
.width('100%')
Flex({
direction: FlexDirection.Row,
wrap: FlexWrap.Wrap,
justifyContent: FlexAlign.Start
}) {
ForEach(this.selectedRed, (num: number) => {
Text(num.toString())
.width(40)
.height(40)
.borderRadius(20)
.backgroundColor('#F44336')
.fontColor('#FFFFFF')
.textAlign(TextAlign.Center)
.fontSize(16)
.fontWeight(FontWeight.Bold)
})
}
.width('100%')
Text('蓝球:')
.fontSize(14)
.fontColor('#2196F3')
.width('100%')
Flex({
direction: FlexDirection.Row,
wrap: FlexWrap.Wrap,
justifyContent: FlexAlign.Start
}) {
ForEach(this.selectedBlue, (num: number) => {
Text(num.toString())
.width(40)
.height(40)
.borderRadius(20)
.backgroundColor('#2196F3')
.fontColor('#FFFFFF')
.textAlign(TextAlign.Center)
.fontSize(16)
.fontWeight(FontWeight.Bold)
})
}
.width('100%')
}
.width('100%')
.padding(10)
.backgroundColor('#F5F5F5')
.borderRadius(8)
Row({ space: 10 }) {
Button('随机选号')
.width('50%')
.height(45)
.backgroundColor('#9C27B0')
.fontSize(14)
.onClick(() => {
this.generateRandomNumbers()
})
Button('重置')
.width('50%')
.height(45)
.backgroundColor('#FF9800')
.fontSize(14)
.onClick(() => {
this.reset()
})
}
.width('100%')
}
.width('100%')
.padding(15)
.backgroundColor('#FAFAFA')
.borderRadius(10)
Column({ space: 10 }) {
Text('模拟开奖')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333')
.width('100%')
Text(`已模拟:${this.simulationCount.toLocaleString()} 次`)
.fontSize(14)
.fontColor('#E91E63')
.width('100%')
if (this.wins.size > 0) {
Column({ space: 5 }) {
Text('中奖记录:')
.fontSize(14)
.fontColor('#333')
.width('100%')
ForEach(this.prizeLevels, (prize: PrizeLevel) => {
if (this.hasWin(prize.level)) {
Row({ space: 10 }) {
Text(prize.name)
.fontSize(14)
.fontColor('#4CAF50')
Text(`: ${this.getWinCount(prize.level)} 次`)
.fontSize(14)
.fontColor('#333')
}
.width('100%')
}
})
}
.width('100%')
.padding(10)
.backgroundColor('#C8E6C9')
.borderRadius(8)
}
Button(this.isSimulating ? '模拟中...' : '开始模拟10万次')
.width('100%')
.height(50)
.backgroundColor(this.isSimulating ? '#9E9E9E' : '#E91E63')
.fontSize(16)
.enabled(!this.isSimulating)
.onClick(() => {
this.startSimulation()
})
}
.width('100%')
.padding(15)
.backgroundColor('#FAFAFA')
.borderRadius(10)
Column({ space: 10 }) {
Text('各奖项中奖概率')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333')
.width('100%')
Column({ space: 5 }) {
ForEach(this.prizeLevels, (prize: PrizeLevel) => {
Column({ space: 3 }) {
Row({ space: 10 }) {
Text(prize.name)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor(prize.level === 1 ? '#FFD700' : prize.level === 2 ? '#C0C0C0' : prize.level === 3 ? '#CD7F32' : '#333')
.width(80)
Text(prize.description)
.fontSize(12)
.fontColor('#666')
.layoutWeight(1)
}
.width('100%')
Text(`概率:${prize.probability}`)
.fontSize(12)
.fontColor('#E91E63')
.width('100%')
}
.width('100%')
.padding(8)
.backgroundColor(prize.level <= 3 ? '#FFF3E0' : '#F5F5F5')
.borderRadius(4)
})
}
.width('100%')
}
.width('100%')
.padding(15)
.backgroundColor('#FAFAFA')
.borderRadius(10)
Column({ space: 5 }) {
Text('温馨提示')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#E91E63')
Text('• 双色球一等奖概率仅约 1/1772万,相当于连续抛硬币24次都是正面')
.fontSize(12)
.fontColor('#666')
.width('100%')
Text('• 如果每周买3次,平均需要约11万年才能中一次一等奖')
.fontSize(12)
.fontColor('#666')
.width('100%')
Text('• 彩票只是娱乐方式,请理性购彩,量力而行')
.fontSize(12)
.fontColor('#666')
.width('100%')
}
.width('100%')
.padding(15)
.backgroundColor('#FCE4EC')
.borderRadius(10)
}
.width('100%')
.padding(10)
}
.width('100%')
.height('100%')
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
}
更多推荐


所有评论(0)