【问题标题】:C++ console TicTacToe: Checking Win ConditionsC++ 控制台井字游戏:检查获胜条件
【发布时间】:2016-12-12 17:01:44
【问题描述】:

游戏板存储为 2D 字符数组。玩家使用数字键盘在棋盘上移动光标,并使用 enter 键选择 - 光标的当前位置存储在两个整数中。

每次移动后,使用以下方法评估棋盘是否获胜。

void checkwin()
{
    //look along lines from current position
    int x = cursorPosX;
    int y = cursorPosY;
    int c = playerTurn ? 1 : 2; //which mark to look for

    for (int xAxis = 0; xAxis <= 2; xAxis++) //look along x axis
    {
        x = WrapValue(0, sizeof(squares[0]), x + 1);
        if (CheckPos(x, y) != c) //if we don't find the same mark, must not be a horizontal line, otherwise, break out.
        {
            x = cursorPosX; //reset x
            for (int yAxis = 0; yAxis <= 2; yAxis++) //look along y axis
            {
                y = WrapValue(0, sizeof(squares[0]), y + 1);
                if (CheckPos(x, y) != c) 
                {
                    y = cursorPosY;
                    //look for diagonal
                    for (int i = 0; i <= 2; i++ )
                    {
                        x = WrapValue(0, sizeof(squares[0]), x + 1);
                        y = WrapValue(0, sizeof(squares[0]), y + 1);
                        if (CheckPos(x, y) != c)
                        {
                            //failed everything, return
                            winConditions = -1;
                            return;
                        }
                    }
                    break;
                }
            }
            break;
        }
    }
    //if we make it out of the loops, we have a winner.
    winConditions = playerTurn ? 0 : 1;
}

我得到错误的结果 - 在不合适的情况下返回平局或获胜。我几乎可以肯定 x 和 y 在某些时候会得到错误的值并开始检查错误的位置。

Visual Studio 在进入 yAxis 循环后停止更新 x 和 y 上的手表 - 我不知道为什么,但它阻止了我跟踪这些值。我是否违反了某处范围界定的规则?这是我唯一使用 x 和 y 作为变量名的地方。

下面的相关换行方法。我的目标是始终能够通过添加来检查其他 2 个空格,无论我在棋盘的哪个位置

int WrapValue(int min, int max, int value)
{
    auto range = max - min;

    while (value >= max)
    {
        value -= range;
    }
    while (value < min)
    {
        value += range;
    }

    return value;
}

我很感激训练有素的眼睛告诉我我在这里做错了什么。非常感谢您的宝贵时间。

【问题讨论】:

  • 你知道怎么调试吗?如果没有:这是学习它的最佳时机。
  • 你建议我从哪里开始?
  • 我建议:1)用调试信息编译程序; 2)在调试器中启动程序; 3)使用next语句命令执行下一条语句,查看变量值; 4) 单步进入函数,看看它们是如何运作的。在网上搜索“c++如何调试小程序”。
  • 旁注,在您的 WrapValue 方法中,如果 value &gt; 2*max 它不会被捕获。分钟相同。你可以把它变成auto range = max-min; while(value &gt;= max) value-=range; while(value&lt;min) value+=range; return value;
  • 这段代码太复杂了,我无法理解。代替所有那些深层嵌套的东西,做三个独立的检查:是否有横向的胜利?有垂直的胜利吗?有对角线的胜利吗?

标签: c++ console tic-tac-toe


【解决方案1】:

嵌套 for 循环是一个糟糕的主意。我通过将代码重构为多个单独的循环来解决这个问题,每个循环只做一件事,而不是通过彼此陷入更深层次的地狱。

for (int xAxis = 0; xAxis <= 2; xAxis++) //look along x axis
{
    x = WrapValue(0, sizeof(squares[0]), x + 1);
    if (CheckPos(x, y) != c) //if we don't find the same mark, must not be a horizontal line, otherwise, break out.
    {
        x = cursorPosX; //reset x
        break;
    }
    else if (xAxis == 2)
    {
        winConditions = playerTurn ? 0 : 1;
        return;
    }
}

for (int yAxis = 0; yAxis <= 2; yAxis++) //look along y axis
{
    y = WrapValue(0, sizeof(squares[0]), y + 1);
    if (CheckPos(x, y) != c)
    {
        y = cursorPosY;
        break;
    }
    else if (yAxis == 2)
    {
        winConditions = playerTurn ? 0 : 1;
        return;
    }
}
...ect

这违反了 DRY,但它确实按预期的方式工作,我相信我以后可以简化它。

虽然我不完全确定为什么以前的方法行不通,但我确实意识到这只是一个糟糕的设计。

【讨论】:

  • 我得记得两天后接受,但我想这个问题现在可以结束了,因为问题已经解决了。
  • 解决您的问题的原因是您在内部 for 循环中声明了新的 x 和 y,这掩盖了外部定义。尽管它是合法代码,但您的编译器应该警告您。您是否忽略了警告?
  • 我总是听取警告,无论是来自我母亲还是来自我的编译器。所以你是说当我给一个在循环外初始化的变量赋值时,它会初始化一个同名的新变量?即使我从未明确初始化过?我想知道您是否可以将我链接到对此进行说明的内容?
  • DRY 是好的设计 :) ...但在 C 中,有时好的设计会导致糟糕的设计。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多