需求说明

• 不同的消费金额获取的红包总额不同，消费金额越大，红包总额就越大，红包总数也就越多；
• 假设有一天，有一种需求是，需要保证参与抢红包的人获得的红包金额在平均数附近波动，也就是尽量的服从正态分布；

功能实现

消费后红包的初始化

• 10-20元的消费金额，可以分享的单个红包金额为10元，可以供5个人抢
• 20-40元的消费金额，可以分享的单个红包金额为20元，可以供8个人抢
• 40-60元的消费金额，可以分享的单个红包金额为30元，可以供10个人抢
• 60-100元的消费金额，可以分享的单个红包金额为40元，可以供10个人抢
• 100元以上的消费金额，可以分享的单个红包金额为50元，可以供10个人抢

`   1:  public class RedPacketsInfo`
`   2:  {`
`   3:      /// <summary>`
`   4:      /// 最大消费金额`
`   5:      /// </summary>`
`   6:      public int MaxAmount { get; set; }`
`   7:   `
`   8:      /// <summary>`
`   9:      /// 最小消费金额`
`  10:      /// </summary>`
`  11:      public int MinAmount { get; set; }`
`  12:   `
`  13:      /// <summary>`
`  14:      /// 红包金额`
`  15:      /// </summary>`
`  16:      public int TotalAmount { get; set; }`
`  17:   `
`  18:      /// <summary>`
`  19:      /// 红包可被分割的数量`
`  20:      /// </summary>`
`  21:      public int RedPacketQuantity { get; set; }`
`  22:  }`

`   1:  private static List<RedPacketsInfo> GetRedPackets()`
`   2:  {`
`   3:      return new List<RedPacketsInfo>()`
`   4:      {`
`   5:          new RedPacketsInfo`
`   6:          {`
`   7:              MinAmount = 1000,`
`   8:              MaxAmount = 2000,`
`   9:              RedPacketQuantity = 5,`
`  10:              TotalAmount=1000`
`  11:          },`
`  12:          new RedPacketsInfo`
`  13:          {`
`  14:              MinAmount = 2000,`
`  15:              MaxAmount = 3000,`
`  16:              RedPacketQuantity = 5,`
`  17:              TotalAmount=1000`
`  18:          },`
`  19:          new RedPacketsInfo`
`  20:          {`
`  21:              MinAmount = 4000,`
`  22:              MaxAmount = 6000,`
`  23:              RedPacketQuantity = 5,`
`  24:              TotalAmount=1000`
`  25:          },`
`  26:          new RedPacketsInfo`
`  27:          {`
`  28:              MinAmount = 6000,`
`  29:              MaxAmount = 8000,`
`  30:              RedPacketQuantity = 5,`
`  31:              TotalAmount=1000`
`  32:          },`
`  33:          new RedPacketsInfo`
`  34:          {`
`  35:              MinAmount = 10000,`
`  36:              MaxAmount = int.MaxValue,`
`  37:              RedPacketQuantity = 5,`
`  38:              TotalAmount=1000`
`  39:          }`
`  40:      };`
`  41:  }`

随机红包的生成时机及处理

`   1:  public class SharedRedPacket`
`   2:  {`
`   3:      /// <summary>`
`   4:      /// 分享人UserId`
`   5:      /// </summary>`
`   6:      public int SenderUserId { get; set; }`
`   7:   `
`   8:      /// <summary>`
`   9:      /// 分享时间`
`  10:      /// </summary>`
`  11:      public DateTime SendTime { get; set; }`
`  12:   `
`  13:      public List<RobbedRedPacket> RobbedRedPackets { get; set; }`
`  14:  }`
`  15:   `
`  16:  public class RobbedRedPacket`
`  17:  {`
`  18:      /// <summary>`
`  19:      /// 抢到红包的人的UserId`
`  20:      /// </summary>`
`  21:      public int UserId { get; set; }`
`  22:   `
`  23:      /// <summary>`
`  24:      /// 抢到的红包金额`
`  25:      /// </summary>`
`  26:      public int Amount { get; set; }`
`  27:   `
`  28:      /// <summary>`
`  29:      /// 抢到时间`
`  30:      /// </summary>`
`  31:      public DateTime RobbedTime { get; set; }`
`  32:  }`

`   1:  //红包随机拆分`
`   2:  Random ran = new Random();`
`   3:  List<double> randoms = new List<double>(redPacketsList.Count);`
`   4:  for (int i = 0; i < redPacketsInfo.RedPacketQuantity - 1; i++)`
`   5:  {`
`   6:      int max = (totalAmount - (redPacketsInfo.RedPacketQuantity - i)) * 1;`
`   7:      int result = ran.Next(1, max);`
`   8:      randoms.Add(result);`
`   9:      totalAmount -= result;`
`  10:  }`
`  11:  randoms.Add(totalAmount);`

`   1:  //正太分布处理`
`   2:  for (int i = 0; i < redPacketsInfo.RedPacketQuantity; i++)`
`   3:  {`
`   4:      double a = Math.Sqrt(Math.Abs(2 * Math.Log(randoms[i], Math.E)));`
`   5:      double b = Math.Cos(2 * Math.PI * randoms[i]);`
`   6:      randoms[i] = a * b * 0.3 + 1;`
`   7:  }`

`   1:  //生成最终的红包数据`
`   2:  double d = originalTotal / randoms.Sum();`
`   3:  SharedRedPacket sharedRedPacket = new SharedRedPacket();`
`   4:  sharedRedPacket.RobbedRedPackets = new List<RobbedRedPacket>(redPacketsList.Count);`
`   5:  for (int i = 0; i < redPacketsInfo.RedPacketQuantity - 1; i++)`
`   6:  {`
`   7:      sharedRedPacket.RobbedRedPackets.Add(new RobbedRedPacket`
`   8:      {`
`   9:          Amount = (int)Math.Round(randoms[i] * d, 0)`
`  10:      });`
`  11:  }`
`  12:  sharedRedPacket.RobbedRedPackets.Add(new RobbedRedPacket`
`  13:  {`
`  14:      Amount = originalTotal - sharedRedPacket.RobbedRedPackets.Sum(p => p.Amount)`
`  15:  });`

测试

`   1:  Console.WriteLine("是否分享输入Y分享成功，输入N退出");`
`   2:  string result = Console.ReadLine();`
`   3:  if (result == "Y")`
`   4:  {`
`   5:      var leftRedPacket = sharedRedPacket.RobbedRedPackets.Where(p => p.UserId <= 0).ToList();`
`   6:      var robbedRedPacket = leftRedPacket[new Random().Next(1, leftRedPacket.Count + 1)];`
`   7:      Console.WriteLine("抢到的到红包金额是：" + robbedRedPacket.Amount);`
`   8:      Console.WriteLine("-------------------------------------------------------");`
`   9:  }`

0 条评论

• 设计模式之中介者模式

提供一个中介对象出来，用于封装一系列对象的交互，从而使各对象不需要直接交互，进一步降低了对象间的耦合度。这是一种行为型设计模式。

• 设计模式之工厂方法模式

定义一个创建对象的接口，但让这个接口的实现类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。也就是说，工厂方法模式会定义一个单独的方法去创建或者管理对...

• 成为0.01%！利用TensorFlow.js和深度学习，轻松阅读古草体文字

古文字识别能力是从事历史研究的学者的必备技能，对于日本的历史研究学者而言，他们的挑战则来自于“古草体”文字，这种文字是古日本使用频率最高的文字之一，也将是他们科...

• 面试官，你再问我滑动窗口问题试试？我有解题模板，不怕！

滑动窗口类问题是面试当中的 高频题 ，问题本身其实并不复杂，但是实现起来细节思考非常的多，想着想着可能因为变量变化，指针移动等等问题，导致程序反复删来改去，有思...

• 安卓Fragment和Activity之间的数据通讯

Fragment是Android3.0之后才推出来的。可以用来做底部菜单，现在很多APP都有用到这个底部菜单。当然TabHost也可以用来做底...

• Android RecyclerView浅析（分类型）

整体上看RecyclerView架构，提供了一种插拔式的体验，高度的解耦，异常的灵活，通过设置它提供的不同LayoutManager，ItemDecoratio...

• 设计模式学习——代理模式（Proxy Pattern）

代理模式是常用的结构型设计模式之一，当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问，为了保证客户端使用的透明性，所访问的真实对象与...

开启图片和文本检查。允许用户在回放期间通过web_find(文本检测)或web_image_check(图片检测)验证函数执行验证检查。这个选项仅应用于HTM...

• .Net使用HttpClient以multipart/form-data形式post上传文件及其相关参数

本次要讲的是使用.Net HttpClient拼接multipark/form-data形式post上传文件和相关参数，并接收到上传文件成功后返回过来的结果...