自动矢量边界检查而不会使我的程序崩溃
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
。
我正在创建一个有效的国际象棋游戏
我的国际象棋引擎有一个棋盘。棋盘是一个二维棋盘[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
。