我想知道如何处理问题,其中有一个过程用于c的问题的许多不同“级别”,最好是以“惯用”的方式。我知道我没有解释得这么好,让我举一个例子:
考虑制作游戏求解器的一般问题,它应该打印出最佳的下一步。我认为它应该检查for
循环中所有可能的移动并查看它是否是一个成功的移动(在如果是这样的话,返回移动,否则检查对手可以对抗你的移动(for loop)的所有可能移动并调用该函数再次找到最佳移动。
但是,我发现这种方法有一些局限性,例如性能(程序会花费时间运行调用函数所需的样板代码等) 并且灵活性有限,因为该函数必须找到一种方法来与调用者进行通信,发现移动有多好。也就是说,如果它可以完成的话。
bestmove()
{
for (;i<maxmove;i++)
{
if(checkifwinning(moves[i])) return;
for (;n<maxopponentmove;n++)
{
bestmove();
}
}
我一直在和haskell搞乱一段时间,所以我担心我的想法是寻求递归解决方案。我希望你能告诉我一种以'c native'方式编写这个函数的方法。 / p>
答案 0 :(得分:3)
C语言允许递归函数。但是,它没有尾递归调用的概念(但在某些情况下,最近的GCC编译器能够将一些尾递归调用优化为纯迭代的机器代码)。
编码递归函数时,应避免过于递归和太大的本地调用帧(因此请使用堆内存)。
答案 1 :(得分:0)
我认为你真正需要的是branch-and-bound类算法:保持一个“开放”动作列表(即尚未考虑)和一个“闭合”动作列表(即已经考虑过)。在C中,最好实现具有两个队列(打开和关闭)。那么你将得到如下算法:
while (open is not empty)
{
pop gameState from open
if (gameState in closed)
continue;
push gameState to closed
for (eachMove)
{
computeNewState();
addStateToOpen();
}
}
与递归方法相比,这有几个优点:
答案 2 :(得分:0)
您正在谈论搜索游戏树以寻找最佳动作;你可以使用像minimax这样的标准算法。你的方法似乎是树的深度优先搜索,终止于第一个获胜的移动;请注意,这不会找到获胜动作的最短路径,也不会防止对手获胜。
有很多方法可以加快搜索游戏树,例如alpha-beta pruning。这样的标准算法是要走的路 - 比担心在C等中调用函数的开销要好得多.C函数调用并不昂贵。在编写C代码时要小心这种“优化” - 无论如何,优化器在这些事情上可能会更好。至少,首先以最直接的方式编写一个版本,这样你就可以对其进行基准测试。你的工作是找到一个好的算法。