gpt4 book ai didi

c# - 一种更优雅的编写决策代码的方式来评估具有不同优先级的多个输入?

转载 作者:可可西里 更新时间:2023-11-01 08:21:01 27 4
gpt4 key购买 nike

我正在为一款游戏编写一些决策 AI,我想出了以下代码。

if(pushedLeft && leftFree && leftExists)
GoLeft();
else if(pushedRight && rightFree && rightExists)
GoRight();
else if(leftFree && leftExists)
GoLeft();
else if(rightFree && rightExists)
GoRight();
else if(pushedLeft && leftExists)
GoLeft();
else if(pushedRight && rightExists)
GoRight();
else if(leftExists)
GoLeft();
else if(rightExists)
GoRight();
// else do nothing...

这是一个相当长的 if 语句流,具有类似的条件!

请注意,它构成了这个漂亮的图案:

L1 L2 L3  -> L
R1 R2 R3 -> R
L2 L3 -> L
R2 R3 -> R
L1 L3 -> L
R1 R3 -> R
L3 -> L
R3 -> R
(nothing) -> 0

这段代码的目的是根据一些传入的状态信息来决定对象应该向左还是向右移动(或者根本不移动)。每条信息都有不同的优先级。我可以将它写在这样的有序列表中:

Highest Priority
----------------
Don't ever move into an invalid space
Prefer to move into an unoccupied space
Prefer to move in the push direction
Prefer to move left
----------------
Lowest Priority

很明显,添加额外的信息输入来做出此决定将使条件的数量增加一倍。并且将这些输入的潜在值数量加倍(例如:允许上/下/左/右)也会使条件数量加倍。 (所以这是 n×m2 条件,对吧?)

所以我的问题是:

是否有一种漂亮、令人满意、优雅的编码方式?

我在想一定有一个很好的“n×m”方式来做到这一点(编辑:我最初在这里有“n+m”,但这似乎是不可能的,因为有 n×m 个输入条件)。适用于我的代码和一般问题的东西?

最好是性能与上述条件版本一样好或更好的东西。理想情况下,避免堆分配的东西 - 对于在游戏开发场景中使用很重要(尽管如有必要,这些总是可以通过缓存等进行优化)。

还有:这个问题是否有任何“Googleable 术语”?我怀疑这不是一个罕见的问题 - 但我不知道它的名字。


更新:一个想法感谢Superpig's answer , 是计算各种选项的分数。像这样:

int nothingScore = 1 << 4;
int leftScore = (1 << 1) + (pushedLeft ? 1 << 2 : 0) + (leftFree ? 1 << 3 : 0) + (leftExists ? 1 << 5 : 0);
int rightScore = (pushedRight ? 1 << 2 : 0) + (rightFree ? 1 << 3 : 0) + (rightExists ? 1 << 5 : 0);

当然有更好的方法来编写评分代码(以及其他评分方法)。然后仍然是计算分数后选择要做什么的问题。当然,可能还有更好的完全不涉及评分的方法。


更新 2: 我有 posted and accepted my own answer here (因为 Superpig 的不是一个完整的解决方案,而且到目前为止,甚至远程都没有其他答案在正确的轨道上)。我没有对各种输出进行评分,而是选择了一种使用位域的选项消除方法。这允许仅使用单个整数进行内存决策。

最佳答案

这本质上是一个分类问题;您想要决策树(或行为树)之类的东西。您正在尝试针对情况(有效性、自由度、插入方向等)获取一堆离散输入,并将结果分类为“上、下、左或右”。

我怀疑,如果您希望 if 语句的长链具有更好或相同的性能 - 至少在指令计数/完成的比较次数方面 - 那么您将必须使您的以你在那里做的方式进行比较。计算所有方向的分数然后检查最大值,或递归地将移动列表划分为首选和非首选等方法最终都会比纯比较序列做更多的工作。

我认为,您可以只构建一个查找表。你有 4 位指示方向是否有效,4 位指示方向是否被占用,2 位指示插入方向,总共 10 位 - 所以有 1024 种不同的情况,每种情况下的行为可以是仅用 2 位(因此,1 字节)进行描述 - 使总表大小为 1024 字节。

单个条目将是这样的结构:

union DecisionSituation
{
unsigned short Index;
struct
{
bool ValidLeft : 1;
bool ValidRight : 1;
bool ValidUp : 1;
bool ValidDown : 1;
bool OccupiedLeft : 1;
bool OccupiedRight : 1;
bool OccupiedUp : 1;
bool OccupiedDown : 1;
Direction PushDirection : 2;
} Flags;
}

您可以通过填写该结构中的标志来描述您的情况,然后读取“索引”值以获得您的查找表索引。

编辑:此外,关于您的评分函数,因为您执行的是严格的位模式,我认为您可以跳过所有三元运算符:

int leftScore = (leftExists << 4) | (leftFree << 3) | (pushedLeft << 2) | 1;
int rightScore = (rightExists << 4) | (rightFree << 3) | (pushedRight << 2) | 0;

// Find the highest scoring direction here

// If none of the scores are at least (1 << 4) it means none of them existed
if(highest score < (1 << 4)) return nothing;

// otherwise just return the highest scoring direction

关于c# - 一种更优雅的编写决策代码的方式来评估具有不同优先级的多个输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10968197/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com