博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
不确定人数的抽奖方法
阅读量:6281 次
发布时间:2019-06-22

本文共 5722 字,大约阅读时间需要 19 分钟。

很多年前就给前公司的年会做过年会抽奖,基本要求就是年会入场时签到,签到的员工都参与抽奖(也可以设置公司高管过滤,不参与抽奖),奖品是预设好的,到时候就是给所有签到员工编号,然后抽奖过程中不断生成一组随机数,这些随机数对应的编号的员工姓名和照片就显示出来,这是很容易想到的算法。

但是还要一种情况就是互联网模式的抽奖,有点像双十一之前,阿里派发红包一样,大家都可以在开始抽奖的时候去抽,奖品也是预设好的,比如1000W的奖金池,派发完毕就抽奖完毕,每个用户可以抽取多次。这种抽奖方式主要是应对抽奖人数不确定的情况,谁也不需要提前签到报名,到了抽奖时间只要注册用户都可以抽奖。

因为抽奖人数不确定,所以采用一人多次抽奖的方案是很好的,对用户来说也是,如果第一次没有抽中,还可以尝试第二次,第三次。具体算法上,其实更简单,因为用户点击抽奖的顺序是随机的,所以我们连随机数都不用用,直接给用户的一次抽奖请求编个自增的号,如果这个号满足中奖规则,那么就分配礼品,返回该抽奖请求中奖结果,如果不满足中奖规则,那么我们就返回未中奖。

为了避免用户频繁的点击,造成服务器过高的负担,我们可以在客户端设置一个动画过程,比如转盘抽奖,可以转几秒以后才请求服务器,看是否中奖,对用户来说也增加了趣味性。为了避免用户不通过客户端,直接发起频繁的HTTP请求来刷奖,我们甚至可以在服务器设置同一个用户的请求时间间隔。

下面贴出我写的一个示例代码部分,我设置了一个自增的整数Sequence ,每个正常的抽奖请求,则Sequence ++,另外设置默认的抽奖基数baseNumber=100,如果能够Sequence能够被baseNumber整除,那么就中奖,否则不中奖:

[RoutePrefix("api/Lottery")]   public class LotteryController : AbpApiController   {      private static volatile int Sequence = 1;       private static IList
winnerList=new List
(); ///
/// 抽奖开始标记,请通过StartNewLotteryRound打开 /// private static bool start = false; ///
/// 所有产品都被抽完了的标记 /// private static bool allPrizeOut = false; ///
/// 当前轮次ID /// private static int currentRoundId = 0; public ILotteryAppService LotteryAppService { get; set; } ///
/// 抽奖基数,只要被该数整除就中奖 /// private static int baseNumber =100; private static IDictionary
userDrawTime=new Dictionary
(); private bool CheckUserDrawTime(int userId) { if (userDrawTime.ContainsKey(userId)) { return userDrawTime[userId].AddSeconds(8) < DateTime.Now;//8s后可以抽奖 } else { return true; } } ///
/// 抽奖一次 /// ///
///
[HttpGet] [Route("Draw/{userId}")] public DrawResult Draw(int userId) { if (!start) { return new DrawResult(400,0, "抽奖未开始"); } if (allPrizeOut) { return new DrawResult(400, 0, "所有奖品已抽完"); } if (!CheckUserDrawTime(userId)) { return new DrawResult(400, 0, "请求过于频繁,请稍后再试"); } int myNumber = Sequence++; userDrawTime[userId] = DateTime.Now;//记录用户这次抽奖的时间 if (myNumber%baseNumber == 0) //中奖啦! { if (winnerList.Contains(userId)) { //用户已经中奖,不用再抽 return new DrawResult(200, 0, "您已经中过奖了"); } var result = LotteryAppService.WriteAWinner(userId, currentRoundId); switch (result.ExceptionType) { case LotteryExceptionType.NoException: { winnerList.Add(userId); return new DrawResult(200, result.PrizeId, ""); } case LotteryExceptionType.AllPrizeOut: { allPrizeOut = true; return new DrawResult(400, 0, "所有奖品已抽完"); } case LotteryExceptionType.InvalidLotteryRound: { return new DrawResult(400, 0, "抽奖轮次无效"); } default: { return new DrawResult(400, 0, "当前用户无效"); } } } return new DrawResult(200, 0, ""); } ///
/// 获得我的奖品对象 /// ///
///
[HttpGet] [Route("MyPrize/{userId}")] public IList
GetMyPrize(int userId) { return LotteryAppService.GetMyPrize(userId); } ///
/// 开始新一轮的抽奖 /// ///
[HttpPost] [Route("StartNewLotteryRound")] [AbpApiAuthorize(PermissionNames.Admin)] public bool StartNewLotteryRound(int roundId) { start = true; allPrizeOut = false; currentRoundId = roundId; return true; } ///
/// 获得当前轮次的奖品和获奖者 /// ///
[HttpGet] [Route("")] public IList
GetLotteries() { return LotteryAppService.GetLotteries(currentRoundId); } ///
/// 获得所有的奖品和获奖者 /// ///
[HttpGet] [Route("All")] public IList
GetAllLotteries() { return LotteryAppService.GetLotteries(0); } ///
/// 清空中奖结果,各种缓存 /// ///
[HttpPost] [Route("Clean")] [AbpApiAuthorize(PermissionNames.Admin)] public bool Clean() { Sequence = 1; start = false; winnerList.Clear(); LotteryAppService.CleanLotteries(); return true; } ///
/// 获取是否显示抽奖图标 /// ///
[HttpGet] [Route("ShowLotteryIcon")] public bool GetShowLotteryIcon() { return LotteryAppService.ShowLotteryIcon; } ///
/// 设置是否显示抽奖图标 /// ///
///
[HttpPut] [Route("ShowLotteryIcon/{show}")] public HttpResponseMessage SetShowLotteryIcon(bool show) { try { LotteryAppService.ShowLotteryIcon = show; return Request.CreateResponse(HttpStatusCode.OK, true); } catch (Exception ex) { var resp = new HttpResponseMessage(HttpStatusCode.BadGateway) { Content = new StringContent("设置ShowLotteryIcon失败:" + ex.Message), ReasonPhrase = "Gateway failed" }; throw new HttpResponseException(resp); } } ///
/// 设置Base Number /// ///
///
[HttpPut] [AbpApiAuthorize(PermissionNames.Admin)] [Route("SetBaseNumber/{number}")] public bool SetBaseNumber(int number) { baseNumber = number; return true; } }

 

转载地址:http://jziva.baihongyu.com/

你可能感兴趣的文章
Java (for循环综合应用)
查看>>
NodeJs——(10)REST风格的路由规则
查看>>
软件可扩展性:来自星巴克的经验
查看>>
Java Cache系列之Guava Cache实现详解
查看>>
深入Log4J源码之LoggerRepository和Configurator
查看>>
System V 消息队列—复用消息
查看>>
vi常用快捷键
查看>>
Code Jam 2010 Round 1A Problem A
查看>>
C语言柔性数组
查看>>
iOS学习之flappyBird游戏的实现
查看>>
Cocos2D v2.0至v3.x简洁转换指南(五)
查看>>
springMVC4(8)模型数据绑定全面分析
查看>>
设计模式 - 适配器
查看>>
CSS之可折叠导航
查看>>
淘宝美工设计师细说何为天猫透明背景
查看>>
【B/S学习总结】我的第100篇CSDN博客
查看>>
[Hadoop]chukwa与ganglia的区别
查看>>
数据挖掘工具分析北京房价 (一) 数据爬取采集
查看>>
IOS项目之弹出动画终结篇
查看>>
iOS开发UI篇—ios应用数据存储方式(XML属性列表-plist)
查看>>