赛博红兔的科技博客

CyberHongTu shares news, insights, and musings on fascinating technology subjects.


Python玩转双色球:我什么时候能中大奖?

大家好,我是赛博红兔。在我第一期的《和大货聊聊天》的节目里提到一句我研究过美国的PowerBall强力球博彩,拿它做了一个预测彩票的项目,结果项目失败了但是Python技巧提高了不少。有朋友对这个项目比较感兴趣,正巧不是在今年2月6日福彩双色球的开奖时,贵州一位“彩民”独中了6.8个亿元的巨奖,让看到的人心痒痒。那么,我们就用Python来构建一个咱们中国福彩双色球的抽奖模型,来模拟一下这个天上掉馅饼的美事。这个项目也比较适合刚学完Python的新手们来上手实践,有些朋友觉得总找不到项目去练习和实践,其实项目不需要很大很复杂,只需要你足够感兴趣,对你的学习生活工作有帮助有意义就行。

现在,我们一起来看一下具体咱们的Python项目。首先,有些朋友不了解双色球的玩法,我先来介绍一下。双色球就是有两组颜色的球组成,彩民需从1到33号中不带重复地选择6个红球号码,然后从1到16号中选择1个蓝球号码。中奖的等级分为多个级别,其中一等奖需要所有红球和蓝球号码完全匹配,也就是6+1。二等奖是全中红球,也就是6+0,三等奖是5+1,四等奖是5+0或者4+1,五等奖是4+0或者3+1,末等奖是2+1,1+1,或者0+1。奖金根据中奖等级和当期销售额进行分配,不同级别的奖金从固定金额到高达数百万甚至数亿元不等。大概就是这么一个情况。

接下来,我们来看看怎么用Python逻辑非常顺畅地来一步步模拟这个双色球的。这段代码模拟156次彩票抽奖,每次抽取1张彩票。红球号码范围是1到33,蓝球号码范围是1到16。每次购买彩票花费2元,记录每次抽奖的奖金。根据红球和蓝球匹配情况确定奖金,奖金分为一等奖到六等奖和“感谢参与”。最后输出总花费、总收入和各奖项的中奖次数。

import random

# 红球,蓝球号码范围
red_balls = range(1, 34)
blue_balls = range(1, 17)

# 每次抽奖的彩票数量
tickets_per_drawing = 1

# 抽奖次数
num_drawings = 156

# 总支出,收入
total_spending = 0
total_earnings = 0

# 奖项历史记录
prizes_history = {
    "一等奖": 0,
    "二等奖": 0,
    "三等奖": 0,
    "四等奖": 0,
    "五等奖": 0,
    "六等奖": 0,
    "感谢参与": 0
}

# 计算奖金的函数


def calculate_prize(my_numbers, winning_numbers):
    # 计算红球匹配数和蓝球是否匹配
    red_matches = len(my_numbers["red"] & winning_numbers["red"])
    blue_match = (my_numbers["blue"] == winning_numbers["blue"])

    # 奖金映射表
    prize_map = {
        (6, True): (700_000_000, "一等奖"),
        (6, False): (28_000_000, "二等奖"),
        (5, True): (3_000, "三等奖"),
        (5, False): (200, "四等奖"),
        (4, True): (200, "四等奖"),
        (4, False): (10, "五等奖"),
        (3, True): (10, "五等奖"),
        (2, True): (5, "六等奖"),
        (1, True): (5, "六等奖"),
        (0, True): (5, "六等奖"),
    }

    # 根据匹配结果得到奖金和类别
    if (red_matches, blue_match) in prize_map:
        prize, category = prize_map[(red_matches, blue_match)]
        prizes_history[category] += 1
    else:
        prize = 0
        prizes_history["感谢参与"] += 1

    return prize


# 购买彩票并计算结果
for _ in range(num_drawings):
    red_drawing = set(random.sample(red_balls, 6))
    blue_drawing = random.choice(blue_balls)

    drawn_numbers = {"red": red_drawing, "blue": blue_drawing}

    for _ in range(tickets_per_drawing):
        total_spending += 2

        my_red = set(random.sample(red_balls, k=6))
        my_blue = random.choice(blue_balls)

        player_numbers = {"red": my_red, "blue": my_blue}
        earning = calculate_prize(player_numbers, drawn_numbers)
        total_earnings += earning

# 打印总支出和总收入
print(f'总花费: ¥{total_spending}')
print(f'总收入: ¥{total_earnings}')
print(prizes_history)

下面这段代码模拟彩票抽奖,直到中奖或达到正利润。红球范围1-33,蓝球范围1-16,每次抽100张彩票。通过随机抽取红球和蓝球计算奖金,记录支出、收入和各奖项中奖次数。绘制年利润图。最终输出总支出、总收入和各奖项中奖次数。我们需要1000多年才中到大奖。不知道大家能不能等这么多久。我知道有一只叫阿德维塔的亚达伯拉象龟,是世界上活的时间最长的动物,活了256岁。美国加洲东部有一棵树,估计活了有4854岁。我就想说咱们这回是每次抽奖都买了一百张彩票,还是算挺狂热的彩民了,因为每星期花六百块钱去买彩票,可不是小数目了。但即使这样,回归到咱们个体上,也用了超过1000年的时间才中了大奖。这个项目,完美地回答了我什么时候能中大奖的问题。我现在心满意足了。

import random
import matplotlib.pyplot as plt

# 红球,蓝球号码范围
red_balls = range(1, 34)
blue_balls = range(1, 17)

# 每次抽奖的彩票数量
tickets_per_drawing = 100

# 抽奖次数
num_drawings = 156

# 总支出,收入
total_spending = 0
total_earnings = 0

# 奖项历史记录
prizes_history = {
    "一等奖": 0,
    "二等奖": 0,
    "三等奖": 0,
    "四等奖": 0,
    "五等奖": 0,
    "六等奖": 0,
    "感谢参与": 0
}

# 支出和收入历史
spending_history = []
earnings_history = []
years = []

# 计算奖金的函数


def calculate_prize(my_numbers, winning_numbers):
    # 计算红球匹配数和蓝球是否匹配
    red_matches = len(my_numbers["red"] & winning_numbers["red"])
    blue_match = (my_numbers["blue"] == winning_numbers["blue"])

    # 奖金映射表
    prize_map = {
        (6, True): (700_000_000, "一等奖"),
        (6, False): (28_000_000, "二等奖"),
        (5, True): (3_000, "三等奖"),
        (5, False): (200, "四等奖"),
        (4, True): (200, "四等奖"),
        (4, False): (10, "五等奖"),
        (3, True): (10, "五等奖"),
        (2, True): (5, "六等奖"),
        (1, True): (5, "六等奖"),
        (0, True): (5, "六等奖"),
    }

    # 根据匹配结果得到奖金和类别
    if (red_matches, blue_match) in prize_map:
        prize, category = prize_map[(red_matches, blue_match)]
        prizes_history[category] += 1
    else:
        prize = 0
        prizes_history["感谢参与"] += 1

    return prize


# 初始化中奖标志、抽奖次数和年份计数器
hit_bigprize = False
drawings = 0
year_count = 0

# 如果没有中最大奖,就继续抽奖
while not hit_bigprize:
    drawings += 1

    # 随机选取6个红球和1个蓝球
    red_drawing = set(random.sample(red_balls, 6))
    blue_drawing = random.choice(blue_balls)

    # 将抽出的号码存储为字典
    drawn_numbers = {"red": red_drawing, "blue": blue_drawing}

    # 购买彩票并计算结果
    for _ in range(tickets_per_drawing):
        total_spending += 2
        my_red = set(random.sample(red_balls, k=6))
        my_blue = random.choice(blue_balls)
        player_numbers = {"red": my_red, "blue": my_blue}
        earning = calculate_prize(player_numbers, drawn_numbers)
        total_earnings += earning

        # 如果中了最大奖,则结束循环
        if earning == 700_000_000:
            hit_bigprize = True
            break

    # 如果有了正利润,则结束循环
    # if total_earnings - total_spending > 0:
    #     hit_bigprize = True

    # 如果达到了一年的抽奖次数,更新年度记录
    if drawings % num_drawings == 0:
        year_count += 1
        spending_history.append(total_spending / 1e4)
        earnings_history.append(total_earnings / 1e4)
        years.append(year_count)
        print(f'{year_count} 年')


# 如果循环结束时不是在156次抽奖结束,也要记录下来
if drawings % num_drawings != 0:
    year_count += 1
    spending_history.append(total_spending / 1e4)
    earnings_history.append(total_earnings / 1e4)
    years.append(year_count)

# 绘制利润图
profits = [earn - spend for earn,
           spend in zip(earnings_history, spending_history)]
plt.figure(figsize=(10, 5))
plt.plot(years, profits, marker='o', linestyle='-', color='b')
plt.title('Double Color Ball Profit Chart')
plt.xlabel('Year')
plt.ylabel('Profit (unit: 10k RMB)')
plt.grid(True)
plt.show()

# 打印总支出和总收入
print(f'总花费: ¥{total_spending}')
print(f'总收入: ¥{total_earnings}')
print(prizes_history)

这里给大家展示的是一个刚学完Python的新人如何去按照现实的双色球玩法逻辑来编译的代码。这段代码其实不是最好的写法有很多可以优化的地方,比如,在抽奖模拟过程中,重复生成彩票和抽奖的操作不是非常高效,有更高效的随机数生成的方法。部分数值比如说彩球数量、每次抽奖的彩票数量都是硬编码,可以定义常量变量来增加灵活性和可读性。还有代码里面包含了重复的一些逻辑,比如说年度记录更新,是可以通过封装函数来优化。当然大家也可以在这个项目之上进行拓展,比如说增加用户的交互来面对不同的投注情况,还可以将结果保存到文件里进行进一步统计分析,还可以模拟别的抽奖玩法等等。我会把代码分享在GitHub和我的博客上,链接贴在下方,后面就交给大伙去玩了。好了今天双色球我们就玩到这里,拜拜!



Leave a comment