如何解决c语言中有许多不同层次(它们是递归的)的问题

如何解决c语言中有许多不同层次(它们是递归的)的问题,c,algorithm,recursion,C,Algorithm,Recursion,我想知道如何处理在c语言中的问题的许多不同“级别”中使用的过程,最好是以“惯用”的方式。我知道我没有充分解释这一点,所以让我举一个例子: 考虑制作游戏求解器的一般问题,它应该打印出下一步的最佳动作。我认为它应该检查for循环中所有可能的动作,看看这是否是一个获胜的动作(在这一轮中),如果是,则返回该动作,否则检查对手可以对你的动作(for loop)进行的所有可能动作并调用函数再次查找最佳移动 但是,我发现这种方法有一些局限性,例如性能(程序将花费时间运行调用函数所需的样板代码等) 灵活性有限,

我想知道如何处理在c语言中的问题的许多不同“级别”中使用的过程,最好是以“惯用”的方式。我知道我没有充分解释这一点,所以让我举一个例子:

考虑制作游戏求解器的一般问题,它应该打印出下一步的最佳动作。我认为它应该检查
for
循环中所有可能的动作,看看这是否是一个获胜的动作(在这一轮中),如果是,则返回该动作,否则检查对手可以对你的动作(for loop)进行的所有可能动作并调用函数再次查找最佳移动

但是,我发现这种方法有一些局限性,例如性能(程序将花费时间运行调用函数所需的样板代码等) 灵活性有限,因为函数必须找到一种方法与调用者交流找到的移动有多好,也就是说,如果可以的话

bestmove()
{
  for (;i<maxmove;i++)
   {
    if(checkifwinning(moves[i])) return;
    for (;n<maxopponentmove;n++)
     {
      bestmove();
     }
   }
bestmove()
{

对于(;iC语言允许递归函数。但是,它没有尾部递归调用的概念(但在某些情况下,最近的GCC编译器能够将一些尾部递归调用优化为纯粹的迭代机器代码)


在编写递归函数时,应该避免太深的递归和太大的本地调用帧(因此使用堆内存)。

我认为您真正需要的是一个类似的算法:保留一个“开放”移动列表(即,尚未考虑)和一个“关闭”移动列表(即,已考虑)。在C中,最好使用两个队列来实现(打开和关闭)。然后您将有如下算法:

while (open is not empty)
{
   pop gameState from open
   if (gameState in closed)
      continue;
   push gameState to closed
   for (eachMove)
   {
       computeNewState();
       addStateToOpen();
   }
}
与递归方法相比,此方法有几个优点:

  • 您确定每个游戏状态只考虑一次吗
  • 您不会“压倒”堆栈

您正在谈论搜索游戏树以找到最佳招式;您可以使用标准算法,如。您的方法似乎是对树进行深度优先搜索,在找到第一个获胜招式时终止;请注意,这不会找到通往获胜招式的最短路径,也不会防止对手获胜


有一些方法可以加快游戏树的搜索速度,例如。这样的标准算法是最好的选择-比担心在C中调用函数的开销要好得多。C函数调用并不昂贵。小心这种“优化”在编写C代码时——不管怎样,优化器在这方面可能会做得更好。至少,首先要以最直接的方式编写一个版本,这样你就有了一些基准。你的工作是找到一个好的算法。

返回是什么意思在这段代码中?似乎搜索会在第一次遇到以前看到的状态时终止。(这里的“return”可能更像C的“continue”?)@gcbenison对不起,我的意思是“continue”。也许应该在“if(gameState in closed)”之后加上“push gameState…”否则“if”语句将始终为真