Python关于抽奖系统的思考与设计思路

一、文章主题

在看到相关的抽奖诈骗报道,有的人却不明白是怎么回事。为了预防被抽奖诈骗,因此,我们通过一些简单的例子来说一说,抽奖更深层的逻辑,让大家直观的看到抽奖背后隐藏的东西,防止上当受骗。

二、抽奖设计思路

首先,先来实现一个简单的抽奖逻辑,我们需要确定每个奖品的概率,并根据概率进行抽取。

第一步:需求

有奖品列表。每一个奖品都有对应的概率。用户抽奖获得对应概率商品。

第二步:建立奖品列表

根据上面的要求,我们建立对应的奖品表,概率我们选用1-100的整数,当然也可以选择0-1。

# 奖品列表和对应的概率,和为100
prizes = {"一等奖": 10,"二等奖": 20,"三等奖": 30,"参与奖": 40 }

第三步:概率实现

这就是一个基础的抽奖逻辑,代码实现难点主要是概率,如何去实现概率,能获得抽中的奖品。

关于概率我们需要使用到random模块,也就是我们需要使用到随机数。这里我这里有两种方式可供选择。

第一种:通过区间实现

抽奖概率选用区间的方式实现,将抽奖的概率分成若干个区间,每个区间对应一个奖品,然后根据随机数的范围来确定中奖的区间。例如,我们可以将抽奖的概率分成以下几个区间:

  • - 区间1:0%~20%,对应奖品A
  • - 区间2:20%~50%,对应奖品B
  • - 区间3:50%~80%,对应奖品C
  • - 区间4:80%~100%,对应奖品D

当用户抽奖时,我们可以生成一个0~100之间的随机数,然后根据随机数所在的区间来确定中奖的奖品。例如,如果生成的随机数是35,那么就会中奖区间2,对应奖品B。

优点:这种方式实现抽奖概率的好处是可以灵活地控制各个奖品的中奖概率,同时也可以根据实际情况进行调整。

缺点:各个奖品的中奖概率之和必须等于100%,否则会导致抽奖结果不准确。

import random
 
# 奖品列表和对应的概率
prizes = {"一等奖":10,"二等奖":20,"三等奖":30,"参与奖":40}
#我们可以看做:
# 一等奖:(0,10]
# 二等奖:(10,30]
# 三等奖:(30,60]
# 参与奖:(60,100]
 
# 抽奖函数
def lottery():
    # 生成一个1~100之间的随机数
    lucky_number = random.randint(0,100)
    # 初始化区间值和奖品名称
    prob_sum_start = 0
    prob_sum_end = 0
    prize_name = None
 
    # 遍历奖品列表
    for name, prob in prizes.items():
        # 累加后一个区间值
        prob_sum_end += prob
        # 如果随机数在计算区间内,则中奖
        if prob_sum_start<lucky_number <= prob_sum_end:
            prize_name = name
            break
# 累加前一个区间值
        prob_sum_start = prob
    #返回随机值和中奖产品
    return lucky_number,prize_name

第二种:通过奖品概率累加实现

我们可以通过概率累加的方式来实现抽奖,首先生成一个1到100之间的随机数,表示本次抽奖的结果。

然后按照奖品的概率依次累加,直到累加的结果大于等于随机数为止。

最后停止累加的奖品概率即为本次抽中的奖品。

例如,如果随机数为50,则按照概率累加的方式,可以得到以下结果:

# 奖品列表和对应的概率,和为100
prizes = {"一等奖": 10,"二等奖": 20,"三等奖": 30,"参与奖": 40 }

10< 50,不是一等奖;

10 + 20 = 30 < 50,不是二等奖;

10 + 20 + 30 = 60 >= 50,是三等奖。

因此,本次抽中的奖品为三等奖。

优点:可以灵活地调整奖品的概率,以达到不同的抽奖效果。这种方法也可以应用于多个奖品的情况,只需要按照相应的概率进行累加即可,简单易懂、实现方便。

缺点:缺点是需要计算每个奖品的累加概率,如果奖品数量较多,计算量可能较大。

import random
 
# 奖品列表和对应的概率
prizes = {"一等奖": 10, "二等奖": 20, "三等奖": 30, "参与奖": 40}
 
 
# 抽奖函数
def lottery():
    # 生成一个1~100之间的随机数
    lucky_number = random.randint(1, 100)
    print(lucky_number)
    # 初始化概率总和和奖品名称
    prob_sum = 0
    prize_name = None
 
    # 遍历奖品列表
    for name, prob in prizes.items():
        # 累加概率总和
        prob_sum += prob
        # 如果随机数小于等于概率总和,则中奖
        if lucky_number <= prob_sum:
            prize_name = name
            break
    return prize_name

第四步:增加特殊机制

在我们参与某些活动,或者某些抽奖之后,总是会被人引诱,被大奖冲昏头脑,那抽奖机制是什么,我们也不清楚,这可如何解决。前面我们可以让每一个奖品按照设置的奖品概率进行抽奖,这时,我们需要增加一些特殊机制,这些机制就是被“诈骗”的机制,或者说,被“安排”的机制。

第一种:想让谁中奖,就让谁中奖

这种方式,主要用在聚会恶搞场合,大家可要注意了,这种就不要线上了,因为你不知道这个抽奖程序是谁写的。

针对这种方式,我们需要增加白名单。判断如果是白名单内的人,那我们就让他种指定奖品。

代码如下:

import random
 
# 奖品列表和对应的概率
prizes = {"一等奖": 10, "二等奖": 20, "三等奖": 30, "参与奖": 40}
#白名单列表
whitelist = ["Tom", "Jerry", "Lucy"]
# 抽奖函数
def lottery(white_user):
    # 生成一个1~100之间的随机数
    lucky_number = random.randint(1, 100)
    print(lucky_number)
    # 初始化概率总和和奖品名称
    prob_sum = 0
    prize_name = None
    
    #判断在白名单内,中一等奖
    if white_user in whitelist:
        return "恭喜您中一等奖"
        # 遍历奖品列表
    else:
        for name, prob in prizes.items():
            # 累加概率总和
            prob_sum += prob
            # 如果随机数小于等于概率总和,则中奖
            if lucky_number <= prob_sum:
                prize_name = name
                break
    return prize_name

第二种:参与了另外一个活动,才可以来抽奖

这种方式增加了资格的验证,也可以是,有用户信息之后,才能参与抽奖,也算是增加了一些安全限制。

如果用户参与了另外一个活动,或者是登录了,才能参与活动,进入活动流程。

代码如下:

import random
 
# 奖品列表和对应的概率
prizes = {"一等奖": 10, "二等奖": 20, "三等奖": 30, "参与奖": 40}
#已参加另外一个活动列表
active_user = []
 
#加法活动
def addition(name):
    active_user.append(name)
    return name+"参加了活动"
 
 
# 抽奖函数
def lottery(name):
    # 生成一个1~100之间的随机数
    lucky_number = random.randint(1, 100)
 
    # 初始化概率总和和奖品名称
    prob_sum = 0
    prize_name = None
 
    # 判断在白名单内,中一等奖
    if name not in active_user:
        return "很抱歉,您没有资格参与活动"
 
    else:
        # 遍历奖品列表
        for name, prob in prizes.items():
            # 累加概率总和
            prob_sum += prob
            # 如果随机数小于等于概率总和,则中奖
            if lucky_number <= prob_sum:
                prize_name = name
                break
    return prize_name
 
#测试一下
print(lottery("Tom"))#如果没有参与加法活动,来参与,无法抽奖
print(addition("Tom"))#Tom先来参与加法活动再去参与活动
print(lottery("Tom"))#参与活动抽奖

第三种:打死都不让你中

这种活动纯纯就是恶心人而做的,但是所有参加的用户完全就是不知道,都会以为是自己的运气差。大奖就在哪里,就是拿不到。

这都不用概率,直接给你出结果,完全就是他的营销手段。

代码如……不如了,都不需要,直接一个return搞定。

第四种:概率都是百分比,但是效果不一样

这种就需要和我们设置的随机范围撤上关系,我们的随机范围是1-100,比例为百分比1-100的整数,但是当我们加上小数之后,就不一样。比如:

1%和1.00%

那现在这两种概率你觉得是一样的吗?

答案肯定是不一样的,第一个是百分之一,第二个则是万分之一。因为第一个没有算小数,第二个还有两位小数,看似相等,其实已经变了。

如下图:这三个箭头指向,所占比例大概就是80%,20%,当我们数据越多,范围就会越广,如果随机,那数据会更容易落到80%。

抽奖概率正确性,我们其实可以从概率的统计定义中来看待。

在一定条件下,重复做n次试验,nA为n次试验中事件A发生的次数,如果随着n逐渐增大,频率nA/n逐渐稳定在某一数值p附近,则数值p称为事件A在该条件下发生的概率。

就是说数值越多,越是能证明概率的正确性。但是,我们抽奖只有一次机会。对于我来说80%肯定比20%更加容易随机。

代码控制:控制随机值,1-10000。

第五种:某荣耀-有机率

有机率估计是某王常用套路了,有机率基本等于没有。文字游戏算是被玩明白了。当然因为用户体量比较大,因此,也可能采用第4种方式,万分之一,或者是百万分之一。

第六种:保底机制

这种机制就是比较明确的,整体意思就是,我已经做好坑你准备了,但是坑了我就收手,让你看到希望,给你大奖。常见的有抽了多少次,我就给你中什么奖品。

这里我们设置保底机制为10次必中一等奖。如果前9次都没有中奖,第10次一定中一等奖。

代码如下:

import random
 
# 奖品列表和对应的概率
prizes = {"一等奖": 1, "二等奖": 2, "三等奖": 3, "参与奖": 94}
 
lottery_num = 0  # 记录已经抽中的一等奖、二等奖、三等奖的次数
# 抽奖函数
def lottery():
    # 生成一个1~100之间的随机数
    global lottery_num
    lucky_number = random.randint(1, 100)
    print(lucky_number,lottery_num)
    # 初始化概率总和和奖品名称
    prob_sum = 0
    prize_name = None
 
    # 遍历奖品列表
    for name, prob in prizes.items():
        # 累加概率总和
        prob_sum += prob
        # 如果随机数小于等于概率总和,则中奖
        if lucky_number <= prob_sum:
            prize_name = name
            break
    if prize_name=="参与奖":
        lottery_num += 1
        if lottery_num == 10:
            return "恭喜你,中一等奖"
        return prize_name
    else:
        lottery_num=0
        return prize_name
 
for i in range(10):
    print(lottery())

三、文章总结

文章主要总结一些基本的抽奖逻辑,主要使用随机数模块,random。可以帮助我们了解和使用随机数模块,更好的使用。

另外,凡是抽奖,必定包含有不确定性和被控制性。因为随机意味着脱离了自己的掌控,并不划算。如果不是信任的机构,那就把他当做概率为0。

其实抽奖的应用,还可以延伸出其他的一些东西,这期过长,下期继续。

原文地址:https://djyqxbc-python.blog.csdn.net/article/details/129658889