C#抽奖算法,附调用实例

前提:设置了奖项内容,中奖概率,奖项个数

算法结构:

算法的具体实现:

1、AliasItemModel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Maticsoft.Web.Mobile.LuckDraw.AliasMethod
{
    class AliasItemModel
    {
        private AliasModel basic;
        private AliasModel extension;

        public AliasItemModel(AliasModel basic)
        {
            this.basic = basic;
        }

        public AliasItemModel(object key, decimal probability) : this(new AliasModel(key, probability)) { }

        public AliasModel Basic { set { this.basic = value; } get { return this.basic; } }
        public AliasModel Extension { get { return this.extension; } }
        public bool isDecomposable()
        {
            if (this.basic.Probability > 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public bool Extensible()
        {
            if (this.extension == null && this.basic.Probability < 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public bool Extensible(AliasModel extension)
        {
            if (extension != null && this.Extensible() && extension.Probability + this.basic.Probability > 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public bool Extensible(AliasItemModel aim)
        {
            if (aim != null && aim.isDecomposable() && this.Extensible(aim.Basic))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public AliasModel Extend(AliasModel extension)
        {
            if (this.Extensible(extension))
            {
                decimal d = 1 - this.basic.Probability;
                this.extension = extension.Split(d);
                return extension;
            }
            else
            {
                return null;
            }
        }

        public decimal Probability { get { return this.basic.Probability; } }
    }
}
View Code

2、AliasMethod

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Maticsoft.Web.Mobile.LuckDraw.AliasMethod
{
    public class AliasMethod
    {
        private List<AliasItemModel> list = new List<AliasItemModel>();
        public AliasMethod(Dictionary<object, decimal> prizes)
        {
            List<AliasModel> models = new List<AliasModel>();
            decimal otherProbability = 1;
            foreach (KeyValuePair<object, decimal> pair in prizes)
            {
                models.Add(new AliasModel(pair.Key, pair.Value));
                otherProbability = otherProbability - pair.Value;
            }
            if (otherProbability > 0)
            {
                models.Add(new AliasModel(null, otherProbability));
            }
            foreach (AliasModel model in models)
            {
                list.Add(new AliasItemModel(model.Key, model.Probability * models.Count));
            }
            foreach (AliasItemModel item in list)
            {
                if (item.isDecomposable())
                {
                    foreach (AliasItemModel item2 in list)
                    {
                        if (item.isDecomposable() && item2.Extensible(item))
                        {
                            item.Basic = item2.Extend(item.Basic);
                        }
                    }
                }
            }
        }

        public object Raffle()
        {
            Random ran = new Random();
            int listIndex = ran.Next(this.list.Count - 1);
            AliasItemModel item = list[listIndex];
            decimal probabilityIndex = decimal.Parse(ran.NextDouble().ToString());
            if (probabilityIndex >= item.Probability)
            {
                return item.Extension.Key;
            }
            else
            {
                return item.Basic.Key;
            }
        }
    }
}
View Code

3、AliasModel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Maticsoft.Web.Mobile.LuckDraw.AliasMethod
{
    class AliasModel
    {
        private object key;
        private decimal probability;

        public AliasModel(object key, decimal probability)
        {
            this.key = key;
            this.probability = probability;
        }
        public object Key { set { this.key = value; } get { return this.key; } }
        public decimal Probability { set { this.probability = value; } get { return this.probability; } }

        public AliasModel Split(decimal d)
        {
            if (d < this.probability)
            {
                this.probability = this.probability - d;
                return new AliasModel(this.key, d);
            }
            else
            {
                return null;
            }
        }
    }
}
View Code

4、RaffleResult(具体场景应用时,可以修改属性)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Maticsoft.Web.Mobile.LuckDraw.AliasMethod
{
    public class RaffleResult
    {
        public bool Success { set; get; }
        public string Message { set; get; }
        public int PrizeLevel { get; set; }  //奖品级别,1等奖,2等奖……
        public int PrizeID { get; set; }
        public int PrizeType { get; set; }  //奖品类型,实物,红包,优惠券……
        public string PrizeName { get; set; }  //奖项内容,10元红包,5元红包,手机……
        public string CardJson { get; set; }
        public int ActivityPrizeUserID { get; set; }
        public int PrizeState { get; set; }  //中奖状态
        public bool isFirst { get; set; }

    }
}
View Code

抽奖事件:                  

DataSet ds = bll.GetList(" PrizeStatus = 1 AND ActivitysSettingID=" + actId);//获取活动的所有奖品信息
                        if (ds != null && ds.Tables[0].Rows.Count > 0)
                        {
                            int prizeId;
                            int prizeCount;
                            Dictionary<object, decimal> dic = new Dictionary<object, decimal>();
                            foreach (DataRow dr in ds.Tables[0].Rows)
                            {
                                prizeId = Convert.ToInt32(dr["PrizeID"]);
                                prizeCount = userBll.GetModelList(" PrizeID=" + prizeId).Count;  //该奖项已经抽中的个数
                                if (Convert.ToInt32(dr["PrizeNum"]) > prizeCount)
                                {
                                    dic.Add(prizeId, decimal.Parse(dr["PrizeCount"].ToString()) / 100);
                                }
                            }
                            AliasMethod.AliasMethod act = new AliasMethod.AliasMethod(dic);
                            object key = act.Raffle();  //执行抽奖
                         
                            if (key != null)
                            {
//中奖了,
//处理中奖之后的逻辑操作
} 
else{
//没中奖
 result.PrizeID = 0;
                                result.PrizeState = 0;
                                result.Message = "很遗憾,没有中奖!";  //没有抽中
                                result.Success = true;
                                result.isFirst = true;
                                //插入中奖记录表
                                ActivityPrizeUserID = InserPrizeUserInfo(actId, openId, username, phone, code, null, drawArea);
                                if (ActivityPrizeUserID > 0)
                                    result.Success = true;
                                else
                                    result.Success = false;

}
}
else
                        {
                            result.Success = false;
                            result.PrizeID = -1;
                            result.Message = "尚未设置奖品信息";
                        }
View Code

以上就是抽奖的整个流程,可以确保每次抽奖的概率都是跟设定的概率一样,并且所中的奖项不会大于后台设置的奖项个数

原文地址:https://www.cnblogs.com/SmilePastaLi/p/7229103.html