前一篇说到根据指定概率抽奖,又查阅了一些资料,发现一般都这么实现。不过由于产生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();
}
}
这样一来,概率设置的低一般是不会中奖的。如图,