【问题标题】:calculate a random action to execute by possibilities根据可能性计算要执行的随机动作
【发布时间】:2019-03-15 16:15:17
【问题描述】:

我有一个包含一些可能操作的枚举

internal enum Action
{
    Stay,
    MoveLeft,
    MoveRight
}

以及一个对象,其中包含有关此操作的当前机会的信息

internal class ActionWithPossibility
{
    public Action Action { get; }
    public int ActionChancePercent { get; }

    public ActionWithPossibility(Action action, int actionChancePercent)
    {
        Action = action;
        ActionChancePercent = actionChancePercent;
    }
}

几率从 0 到 100。带有几率的动作集合可能是

        List<ActionWithPossibility> actionsWithPossibilities = new List<ActionWithPossibility>() {
            new ActionWithPossibility(Action.Stay, 40),
            new ActionWithPossibility(Action.MoveLeft, 30),
            new ActionWithPossibility(Action.MoveRight, 30)
        };

        List<ActionWithPossibility> actionsWithPossibilities = new List<ActionWithPossibility>() {
            new ActionWithPossibility(Action.Stay, 30),
            new ActionWithPossibility(Action.MoveLeft, 10),
            new ActionWithPossibility(Action.MoveRight, 60)
        };

        List<ActionWithPossibility> actionsWithPossibilities = new List<ActionWithPossibility>() {
            new ActionWithPossibility(Action.Stay, 30),
            new ActionWithPossibility(Action.MoveLeft, 60),
            new ActionWithPossibility(Action.MoveRight, 10)
        };

有两点很重要:

  • 可能性的总和为 100。
  • 更多或更少的操作都是可能的。所以行动的数量是未知的。

通过该方法调用随机动作时

    public void NextAction(List<ActionWithPossibility> actionsWithPossibilities)
    {
        int randomNumber = random.Next(0, 100);

        // ...

        Action targetAction = null; // ?
    }

有没有办法计算动作(不使用 ifs)?我想到了这个设置:

  • 动作 A 30
  • 动作 B 10
  • 动作 C 60

我可以总结当前动作的前身,会得到这个结果

  • 动作 A 0 - 30
  • 动作 B 30 - 40
  • 动作 C 休息

但我不知道如何通过代码计算动作。一些帮助会很棒。

这可能与

重复

Percentage Based Probability

但正如我之前提到的,可能的操作数量是未知的,所以我不能选择三个 if 语句。也许有一个技巧可以使用一些数学来完全避免 if 语句。

【问题讨论】:

标签: c#


【解决方案1】:
int threshold = 0;
int randomNumber = random.Next(0, 100);
for (var i = 0; i < actionsWithPossibilities.Count; i++)
{
    var item = actionsWithPossibilities[i];
    threshold += item.ActionChancePercent;

    if (randomNumber <= threshold)
    {
        //first action that's under the defined threshold is placed in result
        result = item.Action;
        break;
    }
}

【讨论】:

    【解决方案2】:

    如果您将操作放在列表中,并希望将生成的随机数映射到正确的对象。你可以这样想:

    LINQ:

    actionsWithPossibilities
       .OrderBy(x => x.actionChancePercent) // Sort probabilities in increasing order
       .First(y => randomNumber <= y.actionChancePercent)
       // Find the correct 'bracket' by checking when the 
       // random number passes the thresholds.
    

    【讨论】:

      猜你喜欢
      • 2016-07-05
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      • 2011-10-29
      • 1970-01-01
      • 2021-10-18
      • 1970-01-01
      • 2021-08-05
      相关资源
      最近更新 更多