您的位置:首页 > 运维架构 > 网站架构

关于网站抽奖活动算法的尝试

2011-02-10 10:17 253 查看
遇到一个需求,某网站为了吸引人气,要开展抽奖活动,需求主要有以下几点:

1.共分一、二、三等奖,要控制一等奖尽量不要一开始就抽掉;

2.活动长期开展,持续时间一周左右,要使每天的各奖项概率趋于一致;

3.为保证每天活动参与人数,要确保在限定人数附近抽出所有奖项;

基于以上几点,做出如下设计:

1.首先要输入天预估总人数,并将奖品平均分到每天,得到各奖项的日均奖品数(可能为小数);

2.计算各奖项的抽奖概率,日均奖品数/日抽奖总人数;

3.产生一个随机双精度数,若小于等于概率则视为抽中;

4.一次抽奖开始时,先抽取三等奖,若中奖则提示,若不中奖则继续抽取二等奖,若再不中奖则抽取一等奖;

5.每次抽奖过后,若抽中奖品则预估总人数-1,并且所有概率重新计算,并应用于下一轮抽奖;

6.若总人数小于一个限定阀值,则停止概率变化,用此概率完成全部抽奖;

7.当天奖品总数小于1时,抽奖结束,小数部分流入后一天继续抽奖。

大概思路如上,设计较为简单,没有技术含量,会有的问题就是理论上后一天一开始抽奖的概率会偏高一些,也曾想用某些数学公式定理来解决,但因为对概率论不了解,不了了之。

顺手贴上第一天所有抽奖的代码,希望感兴趣的朋友多给些宝贵意见!

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Collections;

using System.Threading;

namespace Lottery

{

class Program

{

private static string InputString;//输入字符串

private static int LevelCount;//

private static int DayNum;//

private static int DayUserNum;//

private static int[] arrPrizeNum;//

private static double[] AvgPrizeNum;

private static double TotalPrizeNum;

private static double[] ArProbability;

public static Random rand = new Random((int)DateTime.Now.Ticks);

static void Main(string[] args)

{

ShowInfo();

GetInputNum("请输入奖项总数:", ref LevelCount);

arrPrizeNum = new int[LevelCount];

InputPrizeNum();

GetInputNum("请输入预计抽奖天数:", ref DayNum);

GetInputNum("请输入第一天预估总人数:", ref DayUserNum);

BeginLottery();

}

private static void ShowInfo()

{

Console.WriteLine("欢迎使用随机抽奖系统!");

}

private static void InputPrizeNum()

{

for (int i = 0; i < LevelCount; i++)

{

GetInputNum("请输入 " + (i + 1) + " 等奖奖品数目:", ref arrPrizeNum[i]);

}

}

private static void GetInputNum(string words, ref int target)

{

while (true)

{

Console.WriteLine(words);

InputString = Console.ReadLine();

int temp = SafeParse(InputString);

if (temp != -1)

{

target = temp;

break;

}

else

{

Console.WriteLine("您的输入有误,请输入整型数字!");

continue;

}

}

}

private static int SafeParse(object obj)

{

int temp;

if (!int.TryParse(obj.ToString(), out temp))

{

temp = -1;

}

return temp;

}

private static void BeginLottery()

{

AvgPrizeNum = new double[LevelCount];

ArProbability = new double[LevelCount];

TotalPrizeNum = 0;

for (int i = 0; i < LevelCount; i++)

{

TotalPrizeNum += arrPrizeNum[i];

}

for (int i = 0; i < LevelCount; i++)

{

AvgPrizeNum[i] = (double)arrPrizeNum[i] / (double)DayNum;

}

for (int i = 0; i < LevelCount; i++)

{

ArProbability[i] = (double)AvgPrizeNum[i] / (double)DayUserNum;

}

for (int j = 0; j < 10000; j++)

{

double x = rand.NextDouble();

for (int i = LevelCount - 1; i >= 0; i--)

{

if (x < ArProbability[i])

{

if (AvgPrizeNum[i] > 1)

{

AvgPrizeNum[i]--;

Console.WriteLine("恭喜您,抽到了" + (i + 1) + "等奖!");

LotteryOnit();

//Console.ReadLine();

break;

}

else

{

continue;

}

}

else

{

Console.WriteLine("很遗憾,欢迎下次再来!" + DayUserNum);

x = rand.NextDouble();

LotteryOnit();

continue;

}

}

if (DayUserNum > TotalPrizeNum / DayNum)

{

DayUserNum--;

}

for (int i = 0; i < AvgPrizeNum.Length; i++)

{

if (AvgPrizeNum[i] >1)

{

break;

}

if (i == AvgPrizeNum.Length - 1)

{

Console.WriteLine("共" + j + "位用户参与," + "奖已抽完!");

Console.ReadLine();

}

}

Console.WriteLine();

}

Console.ReadLine();

}

private static void LotteryOnit()

{

for (int i = 0; i < LevelCount; i++)

{

ArProbability[i] = (double)AvgPrizeNum[i] / (double)DayUserNum;

Console.WriteLine("第"+(i+1)+"等奖的概率变为:"+ArProbability[i].ToString());

Console.WriteLine(AvgPrizeNum[i] + " " + DayUserNum);

}

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: