【问题标题】:Function does not return negative value函数不返回负值
【发布时间】:2013-12-08 19:13:41
【问题描述】:

我正在做一个关于 4x4 井字游戏的小项目。我正在使用 Alpha Beta Search 来寻找下一个最佳动作。在 alpha beta 搜索中,我使用了在以下算法的“实用程序”函数中调用的截止评估函数

我成功实现了一切,但问题是效用函数没有返回负值,我真的不知道为什么!以下是函数

private static int utility(GameTreeNode gtn, bool isMin = false)
{
    int nodeValue = 0;
    switch (gtn.NodeBoard.getBoardStatus())
    {
        case Status.Success:
            nodeValue = 50;
            if (isMin) nodeValue = -50;    /// here
            break;
        case Status.Incomplete:
            if (isMin)
                nodeValue = gtn.evaluate(State.X);
            else
                nodeValue = gtn.evaluate(State.O);
            break;
    }
    // case Status.Draw:
    return nodeValue;
}

isMin 在从 MinValue 函数调用时设置为 true

isMin 是 O 的移动,AI 的移动是 X。如果 O 获胜,实用程序应该返回 -50。 但它只返回 0。我调试了程序,它实际上将 -50 分配给了 nodeValuenodeValue 在调试器中更改为 -50),但是当我在 Min 或 Max 函数中收到时,它是零。

注意:整个项目中使用的所有int都是signed int。不使用 unsigned 关键字,如果您认为函数调用者是无符号的

alpha-beta 搜索的完整代码在这里:http://pastie.org/8538015

请朋友们尽快帮忙。

【问题讨论】:

  • 我没有看到在伪代码中将isMin 设置为trueUtility 调用...
  • 在我的代码中,它确实是为了区分 MinValue 和 MaxValue 的调用(以区分 O 和 X 的移动)

标签: c# function return-value tic-tac-toe alpha-beta-pruning


【解决方案1】:

由于您在方法签名中使用了可选参数,因此我提醒您在输入函数时注意您的代码实际运行的内容。你说你调试了它并分配了值,但我没有足够的上下文来知道它是否只发生在许多情况之一。无论如何,请小心那些!

我会这样重写你的函数:

private static int utility(GameTreeNode gtn, bool isMin)
{
    switch (gtn.NodeBoard.getBoardStatus())
    {
        case Status.Success:
            return isMin 
                ? -50 
                : 50;
        case Status.Incomplete:
            return isMin 
                ? gtn.evaluate(State.X)
                : gtn.evaluate(State.O);
        default:
            throw new NotImplementedException("The status is not implemented.");
    }
}

我看到这种方法的一些改进:

  • 您不需要存储一个值并在最后返回它。在您的情况下,当您采用 Status.Success 路径时,您总是将 50 存储到 nodeValue 中,然后有时将 -50 分配给它。除非你坚持在你的函数中有一个返回,否则我认为这种方法更清楚。不过可能只是我的看法。
  • switch 语句中有一个默认值,以便在您的状态未实现时显式抛出异常。
  • 您的函数没有 no 可选参数。我看不到让这个参数可选的好处。在我看来,它看起来只是增加了空间,使调试变得更加困难。

编辑:

基于http://pastie.org/8538015#33,43的代码

看起来您唯一可以让实用程序返回负值的时间是在 private static int MinValue(GameTreeNode gtn, int alpha, int beta) 函数中命中 if (gtn.Nodes.Count == 0) return utility(gtn, true); 时。否则,除非有更多您没有发布的代码,否则对实用程序函数的其他调用将不会达到您所追求的逻辑路径。您在进入那里时提到过,您可以看到 nodeValue 的值已正确分配。

我建议你改变:

// if Terminal-test(state) then return utitly(state)
if (gtn.Nodes.Count == 0) return utility(gtn, true);
gtn.Value = Globals.MAXINT;

// if Terminal-test(state) then return utitly(state)
if (gtn.Nodes.Count == 0)
{
    int retVal = utility(gtn, true);
    return retVal;
}

gtn.Value = Globals.MAXINT;

至少暂时,然后在return retVal 上放一个断点。如果您的实用函数 确实像您说的那样设置了您期望的值,那么当它返回到 MinValue 函数时,它不可能神奇地消失。我感觉发生了一些可疑的事情,代码实际上并没有按照您期望的方式执行。

【讨论】:

  • 我知道可以直接返回,但是在调试器中,直接返回的时候并没有存储值,所以我使用了一个值,这样我就可以介入看看是否完成了不是。另外,我可能在调用者函数中也做了同样的事情。我也在发布 minmax 函数。请
  • 好吧,很公平 :) 等其他代码启动后,我会回来查看。
  • 如果您在调用 utility(gtn, true) 时采用相同的方法将返回值存储在 MinValue 函数内部的临时变量中;,你得到了什么价值?
  • 我在调用实用程序 (gtn, true) 处放置了一个条件断点,如果值低于 -25(检查 -50 左右),该断点会中断,但它永远不会触及断点。此外,我还有一个选择特定节点的控制台输出(通过TreeView,因为GTN 继承TreeNode,你看)打印板、值、alpha、beta。 O 获胜的值始终为 0。我还经历了“步入”,我在实用程序中得到了 nodeValue 到 -50,但在 MinValue 中没有得到
猜你喜欢
  • 2020-07-20
  • 2013-06-27
  • 2016-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-23
相关资源
最近更新 更多