前一篇说到根据指定概率抽奖,又查阅了一些资料,发现一般都这么实现。不过由于产生0-1之间的double问题,对程序作了修改。产生随机数作了简单修改。然后将概率不再作为小数,而是扩大为基数倍。
先看工具类:
先看工具类:
public static class ToolMethods { /// <summary> /// 获取概率的基数 /// </summary> /// <param name="array"></param> /// <returns></returns> public static long GetBaseNumber(double[] array) { long result = 0; try { if (array == null || array.Length == 0) { return result; } string targetNumber = string.Empty ; foreach (double item in array) { string temp = item.ToString(); if (!temp.Contains('.')) { continue; } temp = temp.Substring(temp.IndexOf('.')).Replace(".", ""); if (targetNumber.Length < temp.Length) { targetNumber = temp; } } if (!string.IsNullOrEmpty(targetNumber)) { int ep = targetNumber.Length; result = (long)Math.Pow(10, ep); } } catch { } return result; } /// <summary> /// 获取随机数 /// </summary> /// <param name="random"></param> /// <param name="min"></param> /// <param name="max"></param> /// <returns></returns> public static long GetRandomNumber(this Random random, long min, long max) { byte[] minArr = BitConverter.GetBytes(min); int hMin = BitConverter.ToInt32(minArr, 4); int lMin = BitConverter.ToInt32(new byte[] { minArr[0], minArr[1], minArr[2], minArr[3] }, 0); byte[] maxArr = BitConverter.GetBytes(max); int hMax = BitConverter.ToInt32(maxArr, 4); int lMax = BitConverter.ToInt32(new byte[] { maxArr[0], maxArr[1], maxArr[2], maxArr[3] }, 0); if (random == null) { random = new Random(); } int h = random.Next(hMin, hMax); int l = 0; if (h == hMin) { l = random.Next(Math.Min(lMin, lMax), Math.Max(lMin, lMax)); } else { l = random.Next(0, Int32.MaxValue); } byte[] lArr = BitConverter.GetBytes(l); byte[] hArr = BitConverter.GetBytes(h); byte[] result = new byte[8]; for (int i = 0; i < lArr.Length; i++) { result[i] = lArr[i]; result[i + 4] = hArr[i]; } return BitConverter.ToInt64(result, 0); } }
主要是取随机数和获得当前概率的基数。
抽奖程序,作了一些调整。
class Program { static void Main(string[] args) { List<KeyValuePair<long, double>> elements = new List<KeyValuePair<long, double>>(); elements.Add(new KeyValuePair<long, double>(0, 0.000002)); elements.Add(new KeyValuePair<long, double>(1, 0.000004)); elements.Add(new KeyValuePair<long, double>(2, 0.0001)); elements.Add(new KeyValuePair<long, double>(3, 0.0001)); elements.Add(new KeyValuePair<long, double>(4, 0.0003)); elements.Add(new KeyValuePair<long, double>(5, 0.000004)); elements.Add(new KeyValuePair<long, double>(6, 0.000004)); elements.Add(new KeyValuePair<long, double>(7, 0.00016)); elements.Add(new KeyValuePair<long, double>(8, 0.000008)); elements.Add(new KeyValuePair<long, double>(9, 0.00012)); elements.Add(new KeyValuePair<long, double>(10, 0.0)); elements.Add(new KeyValuePair<long, double>(11, 0.999198)); Dictionary<long, string> prize = new Dictionary<long, string>(); prize.Add(0, @"奖品1"); prize.Add(1, @"奖品2"); prize.Add(2, @"奖品3"); prize.Add(3, @"奖品4"); prize.Add(4, @"奖品5"); prize.Add(5, @"奖品6"); prize.Add(6, @"奖品7"); prize.Add(7, @"奖品8"); prize.Add(8, @"奖品9"); prize.Add(9, @"奖品10"); prize.Add(10, @"奖品11"); prize.Add(11, @"谢谢参与!"); //求出概率基数 long basicNumber = 0; double[] array = new double[elements.Count]; int m=0; foreach (KeyValuePair<long, double> item in elements) { array[m] = item.Value; m++; } basicNumber = ToolMethods.GetBaseNumber(array); //判断设置的概率 double allRate = 0; foreach (var item in elements) { allRate += item.Value; } if (allRate != 1) { Console.WriteLine("奖品概率设置错误!"); Console.WriteLine(allRate); Console.ReadLine(); return; } //抽奖 Random random = new Random(); long selectedElement = 0; while (true) { for (int n = 0; n < 20; n++) { long diceRoll = ToolMethods.GetRandomNumber(random,1,basicNumber); long cumulative = 0; for (int i = 0; i < elements.Count; i++) { cumulative += (long)(elements[i].Value * basicNumber); if (diceRoll <= cumulative) { selectedElement = elements[i].Key; break; } } Console.WriteLine(prize[selectedElement]); } string read = Console.ReadLine(); if (read=="e") { break; } } Console.ReadLine(); } }
这样一来,概率设置的低一般是不会中奖的。如图,