当前位置: 首页 > 知识库问答 >
问题:

在不破坏我的程序的情况下自动进行矢量边界检查

程昕
2023-03-14

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

我的象棋机有一个棋盘。该电路板是一个2D电路板[Y][X],其内部是多个元件。片段是枚举,它代表黑色片段、白色片段和无。

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会导致棋子出界。

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

是否有一种方法可以实现Board[][],以便当我尝试访问超出绑定的索引时,它会抛出错误消息或其他东西而不会使我的程序崩溃?

谢谢

共有1个答案

张光辉
2023-03-14

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

首先是如何确保游戏防止一块棋子出现在棋盘之外。这不是错误处理;您必须首先确保棋子永远不会出现在那里。换句话说,您必须将程序逻辑限制为有效的移动,然后才能将选择呈现给用户(或AI组件)。如果您想在处捕获从抛出的异常,然后将棋盘恢复到有效状态,请立即停止并不要这样做。这将是异常滥用的最佳表现。

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

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

如果您将std::向量包装在自己的类中,这会变得相当容易。当您进行时,您可以使用操作符()简化元素访问:

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

 类似资料:
  • 我最近通过从源代码编译在CentOS机器上安装了Python 2.7.3。Python 2.7.3安装在/opt/python2.7上,当我安装它时,我只需更改/usr/bin/Python以指向新版本。这显然是错误的,因为当我这样做的时候,它打破了百胜。我会得到以下内容。 我更改了/usr/bin/python以指向python 2.6.6,但现在2.6.6是python的默认版本。你知道怎么解

  • 为了记录请求和响应,我添加了一个LoggingRequestInterceptor,它实现了ClientHTTPPrequestinterceptor。。。 响应主体是一个流,如果我将其读取到我的拦截器中,TestRestTemplate将无法将其反序列化到我的对象模型中。换句话说,当我调用testRestTemplate时。获取…我将始终获取空对象(即使我看到对象我的响应)。 要解决RestTe

  • 假设我有两个类叫做ad。 它们都实现了。 对于只有两种方法,分别称为和。 一切都很好。但是,虽然这似乎很好地利用了s,但我认为如果我需要向这个添加方法,实现就会中断,即我需要去实现这些类中的新方法,这打破了“封闭-开放原则”。 所以我想,除了,如果将来需要添加新方法,我还会使用类。 例如,。 这听起来是个好计划(如果不是,请纠正我)。 但问题是,如果这些类已经有其他类了怎么办?在这种情况下,我不能

  • 我在一个名为的文件夹中构建了一个第三方静态库,并将得到的*.lib文件复制到我的projects文件夹结构中。除了*.lib之外,我还放置了*.pdb文件。然后我删除了,假设不再需要它。这是以前为其他库工作的,它遵循了似乎是一种常见的实践。 但是,当我在调试配置中构建项目时,我会得到许多类似于这样的LNK4099警告(大致翻译): 我验证了*.pdb文件就在*.lib文件旁边。作为一个测试,我将它

  • 问题内容: 我想重写类上的方法以执行某些操作,但我不想破坏默认行为。 正确的方法是什么? 问题答案: 覆盖应该没问题-只能作为最后的选择,即,如果实例中没有与名称匹配的属性。例如,如果您访问,则仅当没有调用属性时才会被调用。如果该属性是您不想处理的属性,请引发: 但是,与不同,首先会被调用(仅适用于新样式类,即从对象继承的类)。在这种情况下,您可以保留默认行为,如下所示: 有关更多信息,请参见Py

  • 有什么方法可以确定已经附加到场景但设置为不可见的节点的边界(尤其是高度和宽度)吗? 我想仅在其宽度超过100px时才在屏幕上显示标签...但它始终为 0: sysout的结果:(还有n.getWidth()也好不到哪里去) BoundingBox[minX: 0.0, minY: 0.0, minZ: 0.0,宽度: 0.0,高度: 0.0,深度: 0.0, maxX: 0.0, maxY: 0.