自动矢量边界检查而不会使我的程序崩溃

Automatic vector boundary checking without crashing my program

我正在创建一个有效的国际象棋游戏

我的国际象棋引擎有一个棋盘。棋盘是一个二维棋盘[Y][X],里面是棋子。 Pieces 是一个枚举,代表黑块,白块,NONE。

class ChessBoard
{
   vector<vector<Piece>> board(); //I made it 8*8 in the constructor
   enum Piece{NONE, white pieces, black pieces etc..}
}

我的问题是验证我的棋盘中是否有正方形。请让我详细说明。例如,当查看 A2 兵的可能移动时,兵可以向上移动 1 2 或从左向右捕获,或者从左向右移动:

(X,Y+1), (X,Y+2), (X+1,Y+1), (X-1,Y+1), (X+1,Y+2), (X-1,Y-2)

但是,如您所知,X-1会导致棋子出界。

是的,我可以实现一个简单的 bool isSquareValid() 函数。但这意味着,无论我试图访问或设置 board[][],我都需要调用此函数。

有没有一种实现 Board[][] 的方法,这样当我尝试访问超出绑定的索引时,它会抛出一条错误消息或其他内容而不会使我的程序崩溃?

谢谢

你混淆了两个不同的问题。

首先是如何确保游戏防止棋子落在棋盘外。这是不是错误处理;你必须确保这件作品从一开始就不会在那里结束。换句话说,您必须将程序逻辑限制为有效移动 ,然后才能将选择呈现给用户(或 AI 组件,就此而言)。如果您喜欢捕获从 at 抛出的异常然后将面板恢复到有效状态的想法,请就此打住,不要那样做。这将是最好的异常滥用。

第二个是如何处理代码中的错误导致的错误。您可能已经编写了代码来防止游戏将棋子放在棋盘之外,但您可能犯了一个错误,因为我们都这样做,所以您最终会得到非法的向量索引。在这种情况下,operator[] 导致的崩溃实际上是一件好事,因为立即终止错误程序通常是发生在你身上的最好的事情。另一种方法是 "somehow continue" 继续使用损坏的数据和破坏的游戏规则,甚至可能没有足够快地注意到错误。

因为不能保证错误的 operator[] 调用会导致崩溃,并且强制运行时库执行检查可能有点麻烦(错误的 operator[] 索引在形式上是未定义的行为,当然),您可能想要添加一些您自己的 assert 语句,并确保 NDEBUG 不会阻止它们完成它们的工作。

如果您将 std::vector 包装在您自己的 class 中,这会变得容易得多。当您使用它时,您可以使用 operator():

简化元素访问
class Board
{
public:
    Piece& operator()(int x, int y)
    {
        assert(x >= 0);
        assert(x < 16);
        assert(y >= 0);
        assert(y < 16);
        return data[y][x];
    }

    Piece operator()(int x, int y) const
    {
        assert(x >= 0);
        assert(x < 16);
        assert(y >= 0);
        assert(y < 16);
        return data[y][x];
    }

    Board()
    {
        for (int row_index = 0; row_index < 16; ++row_index)
        {
            data.emplace_back(16, Piece::None);
        }
    }

private:
    std::vector<std::vector<Piece>> data;
};

另请注意,std::vector 不是棋盘的最佳选择,因为棋盘不会缩小或增大。考虑改用 std::array