1. 彩票中奖概率分析
  • 功能:模拟双色球等彩票规则,计算中奖概率,体验“小概率事件”的不可能性。
    模拟双色球等彩票规则(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')
  }
}
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐