相同概率的抽奖程序另类实现——使用数据库,无需数学原理

  抽奖,是很多企业、聚会的常见玩乐形式,光彩绚丽的抽奖屏幕背后,是计算程序+抽奖用户信息。程序=算法+数据结构。

好,说抽奖程序的的实现吧。这个实现一般需要应用数学原理。而本文的方法是我在参加一次婚礼的抽奖体验后突然想到的,一种比较简单、无需数学原理的方法。

功能:能按照相同概率,从用户集合中抽出随机的部分用户集合作为中奖者。抽奖可以进行多次,对已中奖的用户不会重复抽取。

  使用技术:

1.SqlServer数据库,使用NewID()作为select随机筛选函数

2.sql随机函数

3.为了快速方便的搭建原型,使用EF 4.1 DB first,然后代码生成Model类(我在快速开发原型是喜欢EF,讨厌sql-实体转换。能让我从sql中解放出来,专注业务逻辑。只有

当需要的sql逻辑比较复杂,EF难以实现或效率不行时我才写sql-实体转换)。

  主要逻辑:

1.建立LotteryUsers(抽奖用户的英文词组)表,定义用户信息、以及是否已中过奖的标志位IsLotteried,默认都是false-0(IsDelete-该用户是否已删除、无效)。

2.执行sql查询出定量的中奖用户集合 :

SELECT TOP(@chooseCount) * FROM LotteryUsers lu WHERE lu.IsDeldte = 0 AND lu.IsLotteried = 0  ORDER BY NEWID()

并且将这些中奖用户的IsLotteried字段设置为true-1

3.控制台显示中奖的用户集合

DB建表语句:

 1 CREATE TABLE [dbo].[LotteryUsers](
 2     [Id] [int] IDENTITY(1,1) NOT NULL,
 3     [JobNumber] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,
 4     [Name] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,
 5     [IsLotteried] [bit] NOT NULL,
 6     [IsDeldte] [bit] NOT NULL,
 7  CONSTRAINT [PK_LotteryUsers] PRIMARY KEY CLUSTERED
 8 (
 9     [Id] ASC
10 )

结构、示例数据:

程序结构:

代码(使用EF 4.1,实体生成模型),代码细节、EF技术看不懂没关系,了解原理即可:

 1 static void Main(string[] args)
 2         {
 3             //添加测试数据:用户信息
 4             ////using (LotteryContext context = new LotteryContext())
 5             ////{
 6             //    for (int i = 1; i < 101; i++)
 7             //    {
 8             //        LotteryUser user = new LotteryUser
 9             //        {
10             //            JobNumber = i.ToString("00000"),
11             //            Name = "niu"+i.ToString(),
12             //            IsLotteried = false,
13             //            IsDeldte = false,
14             //        };
15             //        context.LotteryUsers.Add(user);
16             //    }
17             //    context.SaveChanges();
18             //}
19
20             //从用户集合中随机抽取部分中奖用户显示
21             var lotteryUsers = GetPrizeUsersAndUpdatePrized(10);
22             foreach (var lotteryUser in lotteryUsers)
23             {
24                 Console.WriteLine(string.Join(",", lotteryUser.Id, lotteryUser.JobNumber, lotteryUser.Name));
25             }
26
27         }
28
29         /// <summary>
30         /// 从用户集合中随机抽取部分中奖用户,并将这些用户更新为已中奖、下次不会重复中奖
31         /// </summary>
32         /// <param name="chooseCount">指定中奖用户个数</param>
33         public static List<LotteryUser> GetPrizeUsersAndUpdatePrized(int chooseCount)
34         {
35             List<LotteryUser> lotteryUsers = new List<LotteryUser>();
36             using (LotteryContext context = new LotteryContext())
37             {
38
39                 string lotteryUsersSql = @"SELECT TOP(@chooseCount) * FROM LotteryUsers lu
40                                         WHERE lu.IsDeldte = 0 AND lu.IsLotteried = 0
41                                         ORDER BY NEWID()";
42                 lotteryUsers = context.LotteryUsers.SqlQuery(lotteryUsersSql
43                     , new SqlParameter("@chooseCount", chooseCount)).ToList();
44                 //foreach (var lotteryUser in lotteryUsers)
45                 //{
46                 //    Console.WriteLine(string.Join(",", lotteryUser.Id, lotteryUser.JobNumber, lotteryUser.Name, lotteryUser.IsLotteried, lotteryUser.IsDeldte));
47                 //}
48
49                 //更新已得过奖状态为:是
50                 foreach (var lotteryUser in lotteryUsers)
51                 {
52                     lotteryUser.IsLotteried = true;
53                 }
54                 context.SaveChanges();
55
56                 return lotteryUsers;
57             }
58         }

就这样,lotteryUsers即是中奖的用户。若要继续抽奖,只要再调用GetPrizeUsersAndUpdatePrized()即可,中奖用户不会重复。

---------------------------------------------备注、其他----------------

1.对于某些抽奖,若要内定某些VIP中某个奖,最好不要写死、在配置文件中写上VIP的名字,在抽奖函数中传入这些VIP的名单、直接确认。

2.对于某些次VIP们,若需要提高中奖概率,需要待议。可能实现的方法有:在users表中加上权重Pritory值,然后再做某些操作;或者采用其他较复杂的数学实现方法。

3.我的程序不注重程序\DB效率,所以未经优化。但是实际上,一般抽奖用户也就1W人以下,完全不存在性能问题。(中国16亿人全名抽奖,淘宝京东等全站抽奖数据量很大的,需要另行优化)。

时间: 2024-10-16 14:01:21

相同概率的抽奖程序另类实现——使用数据库,无需数学原理的相关文章

C# 做一个指定概率的抽奖程序

static void Main(string[] args) { //各物品的概率保存在数组里 float[] area = new float[4]{ 0.980f, 0.550f, 0.230f, 0.010f }; //单次测试 //Console.WriteLine(Get(area)); //批量测试 int[] result = new int[4]{ 0, 0, 0, 0 }; for (int i = 0; i < 1770000; i++) //为了比对结果方便,这里循环的次

不同概率的抽奖

今天为大家写个小程序. 工作中有遇到一些抽奖的活动,但是你懂得,抽奖物品的概率肯定不是一样,你会发现好的东西很难抽到,经常抽到一些垃圾的东西,嘿嘿,这就是本文要说的,我们要控制抽奖物品的概率.还有顺便说一句,网上这种小程序几乎没有,很多都是等概率的抽奖balabala- 需求很简单,为了更加形象,这里我们列一个表格来显示我们抽奖的物品和对应的概率(没有边框,大家凑合着看看吧,不想改造Octopress的样式了) 序号 物品名称 物品ID 抽奖概率 1 物品1 P1 0.2 2 物品2 P2 0.

javascript实现抽奖程序

昨天开年会的时候看到一个段子说唯品会年会抽奖,结果大奖都被写抽奖程序的部门得了,CTO现场review代码. 简单想了一下抽奖程序的实现,花了十几分钟写了一下,主要用到的知识有数组添加删除,以及ES5 数组新增的indexOf,filter方法, 为了刷新页面后仍能保存已中奖记录,用了localStorage存盘. 刚开始是用随机数直接取编号,发现要剔除已中奖的人很麻烦,如果重复要递归调用,如果中奖的人太多到最后随机数取到已中奖的人概率太大,所以换用两个数组实现,一个记录已中奖的号码,一个记录未

使用jQuery+PHP+Mysql实现抽奖程序

抽奖程序在实际生活中广泛运用,由于应用场景不同抽奖的方式也是多种多样的.本文将采用实例讲解如何利用jQuery+PHP+Mysql实现类似电视中常见的一个简单的抽奖程序. 查看演示 本例中的抽奖程序要实现从海量手机号码中一次随机抽取一个号码作为中奖号码,可以多次抽奖,被抽中的号码将不会被再次抽中.抽奖流程:点击“开始”按钮后,程序获取号码信息,滚动显示号码,当点击“停止”按钮后,号码停止滚动,这时显示的号码即为中奖号码,可以点击“开始”按钮继续抽奖. HTML <div id="roll&

幸运大转盘-jQuery+PHP实现的抽奖程序

原文  https://www.helloweba.com/view-blog-215.html 准备工作 首先要准备素材,抽奖的界面用到两张图片,圆盘图片和指针图片,实际应用中可以根据不同的需求制作不同的圆盘图片. 接着制作html页面,实例中我们在body中加入如下代码: <div class="demo">     <div id="disk"></div>     <div id="start"&

我的第三个springboot项目,servlet实现一个转盘抽奖程序

继上面第二个springboot项目后,今晚应朋友需求帮忙写个抽奖程序,想着就用springboot+servlet去发布一个服务给前端直接调用或者后端直接调用. 下面来介绍一下: 1.不错,依然需要一个Application的启动springboot的入口 import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;

如何用 Python 写一个简易的抽奖程序

不知道有多少人是被这个头图骗进来的:) 事情的起因是这样的,上周有同学问小编,看着小编的示例代码敲代码,感觉自己也会写了,如果不看的话,七七八八可能也写的出来,但是一旦自己独立写一段程序,感觉到无从下手. 其实这个很正常,刚开始学习写代码,都是跟着别人的套路往下写,看的套路少,很难形成自己的套路,这就和做数学题是一样的,做一道题就想会所有的题目,这个可能性微乎其微,都是通过大量的练习来摸索到自己的套路. 正好快过年了,各个公司都会搞一些抽奖活动,小编今天就来聊一下,如果要写一个简单的抽奖程序,小

jQuery实现圆盘活动抽奖程序效果

<script type="text/javascript" src="jquery-1.7.2.min.js"></script> <script type="text/javascript" src="jQueryRotate.2.2.js"></script> <script type="text/javascript" src="jqu

十分简单的年会抽奖程序

年会那个抽奖程序崩溃实在令人印象太深刻了,所以自己弄了一个简单版本的... data=[] #从数据库或者文件获取员工抽奖id,放到data iNum= raw_input("please input the numbers:\n")#抽几个人 # method= raw_input("please input the method:\n")#做所谓奇偶数抽奖,没意义 allwindata=[] while iNum: windata=[] for i in ran