C#中的随机加权

我正在用C#创建游戏,游戏的关键部分是随机性。 它本质上是一个摔跤模拟器,根据许多因素,例如摔跤手属性和当前动量,在桌子上选择“移动”。

然后,在符合此条件的所有移动中,选择使用Random对象执行随机选项并在LINQ中跳过/获取但这实际上是不够的。 我想要做的是重量移动选择的概率(我已经在移动表上有一个列,对于1到100之间的整数)。 我如何在随机行选择中实现此权重?

这不是太难。 我没有代码可以使用所以我假设你有对象Move一个属性在一个数组内的权重和所有权重总和达到100.0(并不重要)。 现在你按权重降序对数组进行排序,选择一个0到99之间的随机数,并迭代所有这些减少你的随机数。 一旦它不再是正面,你就停止并选择当前的指数/移动

 var value = rnd.NextDouble()*100.0; foreach(var move in moves.OrderByDescending(m => m.Weight)) { value -= move.Weight; if (value <= 0) return move; } 

当然你可以将排序或甚至选秀权缓存到一个大数组中并使用随机索引(为了表现)但我希望原则应该清楚。

正如乔治建议的那样 - 这里有一个版本,您可以假设权重总计为100:

 double _weightSum; ... // initialize the Sum somewhere _weightSum = moves.SumBy(m => m.Weight); Move GetRandomMove() { var value = rnd.NextDouble()*weightSum; foreach(var move in moves.OrderByDescending(m => m.Weight)) { value -= move.Weight; if (value <= 0) return move; } } 

有些代码可以帮助我准确理解您的需求,但我建议使用Random .NET库函数。 有些文档可以在这里找到:

http://msdn.microsoft.com/en-us/library/system.random.aspx

此示例生成5个随机整数

 Random rand = new Random(); Console.WriteLine("Five random integer values:"); for (int ctr = 0; ctr <= 4; ctr++) Console.Write("{0,15:N0}", rand.Next()); Console.WriteLine(); 

这将使它与当前时间一起播种,使其“更随机”。 如果您想要可重复的测试,可以在测试时使用常量对其进行播种。

加上每个可能移动的总重量。

将每一个除以该总数,因此您已将范围标准化为0..1。

获取该范围内的随机数。 为每个移动选择一致的顺序,然后选择随机数所在的顺序。

我看着基本上和卡斯滕做同样的事情,但是和Linq在一起。

给定移动是一组Move,每个Move都有一个整数属性Weight

 public Move PickRandomMove() { var allMovesWeight = moves.Sum(m => m.Weight); // pick a unit of weight at random, then shift it along by the weight of the // first move so that there will always be an element in the TakeWhile results var randomPick = new Random().Next(0, allMovesWeight) + moves.First().Weight; return moves.TakeWhile(move => (randomPick -= move.Weight) > 0).Last(); } 

我怀疑有更清晰的表达TakeWhile如何工作的方式,但希望你能得到这个想法