这是C#
我正在使用一个每隔几秒随机计算的变量来生成实体,它是一个在0到100之间随机生成的数字。目前我的系统使用了一堆if / else语句,从最难得的机会开始,最常见的。
如果骰子在32处滚动,并且实体有35%的机会产生,它将产生而不是产生更常见的实体,可以说70%的时间。但是,在大量的if / else语句中执行此操作看起来非常难看,我确信还有另一种方法。
有什么建议吗?
Psuedo我正在做什么
int dice = RandomNumber(0-100);
if(dice < 35) SpawnEntity(Gem);
else
if(dice < 60) SpawnEntity(Crate);
这非常......非常难看。它确实有效,但它很难看。我确信有更好的方法可以做到。
答案 0 :(得分:3)
这将消除一些if冗余并保持初始化更清洁。
var actions = new Dictionary<int, Action>
{{35, () => SpawnEntity(Gem)},
{60, () => SpawnEntity(Crate)}};
foreach(var kvp in actions.OrderBy(kvp => kvp.Key))
if (dice < kvp.Key) {
kvp.Value();
break;
}
正如Alex所提到的,您可能需要使用SortedDictionary或LINQ在迭代期间对其进行排序。还要记住,你并没有停留使用Dictionary
,你可以通过继承IEnumerable并使用适当的add方法来声明自己的集合类型并具有相同的初始化序列。
答案 1 :(得分:0)
我认为没有。 switch
语句不起作用,因为case
标签必须是常量值,而不是范围。
如果要使代码具有通用性,可以定义包含范围和相应实体类型的数据结构。然后编写检查此类结构列表的代码,以找出随机数落入的范围,并创建相应的实体。这将消除所有if / else语句,并使添加新实体或更改其范围更容易一些。但是,如果您创建的一组内容定义明确且不变,则这不是必需的。
你甚至可以进一步抽象它并创建一个实用函数,它接受一组Action
个对象,每个对象都有一个相应的“权重”,然后随机选择并执行Action
个中的一个概率与其重量成正比。
// Randomly executes one of the given actions (KVP values). The probability
// of a given action being chosen is proportional to its weight (KVP key).
public static void RandomlyExecute(
Random random,
IEnumerable<KeyValuePair<double, Action>> choices)
{
double totalWeight = Enumerable.Sum(choices, choice => choice.Key);
double x = random.NextDouble() * totalWeight;
double y = 0;
foreach (var choice in choices)
{
y += choice.Key;
if (x <= y)
{
choice.Value();
break;
}
}
}