C# 超出范围的扫雷艇例外

C# 超出范围的扫雷艇例外,c#,C#,我正在尝试创建一个类来检查被检查瓷砖周围的地雷数量。但问题是我的范围设置为1-max height。如果PosY和posX是1和1,检查左上角的平铺,它将检入到Board数组,例如Board[0,0],但它超出范围,但由于我们没有任何平铺可以检查它的左、上和斜左,它将给出一个例外,即它超出范围 public int GetMineCount(int posY, int posX) { int count = 0; if (Board

我正在尝试创建一个类来检查被检查瓷砖周围的地雷数量。但问题是我的范围设置为1-max height。如果PosY和posX是1和1,检查左上角的平铺,它将检入到Board数组,例如Board[0,0],但它超出范围,但由于我们没有任何平铺可以检查它的左、上和斜左,它将给出一个例外,即它超出范围

public int GetMineCount(int posY, int posX)
        {
            int count = 0;
            if (Board[posY-1, posX-1] == CellState.Mine)
                count++;
            if (Board[posY, posX-1] == CellState.Mine)
                count++;
            if (Board[posY + 1, posX - 1] == CellState.Mine)
                count++;

            if (Board[posY + 1, posX] == CellState.Mine)
                count++;

            if (Board[posY + 1, posX + 1] == CellState.Mine)
                count++;
            if (Board[posY, posX+1] == CellState.Mine)
                count++;

            if (Board[posY-1, posX+1] == CellState.Mine)
                count++;

            if (Board[posY-1, posX] == CellState.Mine)
                count++;

            return count;


        }

是否有一个好的做法,如果数组是我们的范围,它将不计算它。

如果输入是0,0,这一行:

if (Board[posY-1, posX-1] == CellState.Mine)
将尝试访问索引-1,-1。根据定义,Wich永远不可能在范围内

你面临着一个由来已久的问题:制作一个游戏板,看着所有的邻居,而不是酸溜溜地看着游戏板外面。我只能想出几个办法来解决这个问题:

添加一层1 elemet厚的边界空间,该边界空间不显示。正确地标记它。用代码解释它。但在输出过程中忽略它。 使函数访问每个方向。然后,该函数将处理不正确的索引。然而,这是大量的写作工作。而且抄袭会让人难以阅读。 我想到了第三条路。一个单独的函数,其唯一目的是验证索引是否有效。这两个索引必须>=0,但在此维度中我个人的偏好是将数组变宽两行两列,这样你就可以在电路板周围有一个边框。所以一块10x16地雷的板实际上是一个12x18的阵列。所有0,Y,11,Y,X,0和X,17的值都将保存CellState.Border,这意味着您不检查该单元格是否有地雷。您的活动板将从1,1到10,16,这在您的坐标系中也很好! 这确实意味着您必须检查Board[X,Y]是否设置为CellState.Border。如果是,那就别算地雷!忽略它。。。否则,X-1、X+1、Y-1和Y+1的值将始终在范围内,因为这些值将从0,0到11,17。 这是一个简单的技巧,可以避免添加if语句。当然,您可以随时检查所要求的值是否在范围内。 我疯狂的头脑现在正在想一种方法来避免你已经在使用的许多if语句。但由于我不知道您对C有多熟悉,我正在避免使用任何更优雅的解决方案,这些解决方案也有点难以理解。但是,我建议您采取稍微不同的方法! 你看,你在计算每个单元的地雷数量。但是,一旦你放置了地雷,你的阵列就可以拥有正确的地雷数量!你在板上放置了N个地雷,因此对于你放置的每一个地雷,你会立即增加周围所有单元格的地雷数量。这意味着您不需要任何if语句来检查计数。你已经知道伯爵了!但这也意味着Board阵列需要比CellState值多一点的数据。您可以创建一个具有CellState属性、MineCount属性和Visited属性的Cell类。因此,最初,所有单元格的地雷计数值为0,并且对于您放置的每个地雷,所有周围单元格的地雷计数都会增加1。 不过,这不会解决范围异常。为此,您实际上必须检查坐标是否在范围内,或者像我提到的那样在数组周围添加边框

正如我所说,我不知道您的经验有多丰富,但对于更高级的解决方案,您可能需要创建一个函数:

public CellState GetCellState(int posY, int posX)
{
    if (posX < 0) return CellState.Invalid;
    if (posY < 0) return CellState.Invalid;
    if (posX >= MaxX) return CellState.Invalid;
    if (posY >= MaxY) return CellState.Invalid;
    return Board[posY, posX];
}
现在,单个函数将检查每个单元格是否在正确的范围内。这四个if语句可以合并为一个,但我这样写是为了清晰。不过,您的CellState枚举现在需要包含无效值。
不过,这仍然不是我喜欢的方法。但我正在考虑的解决方案解释起来有点复杂,而且不涉及数组。。。当我放置地雷时,我会计算地雷数量,而不是之后…

为什么板[0,0]会超出范围?我知道你看错地方了。您是否在调试器中签入了发生错误时的值。最好的做法是事先检查位置的值,以便防止异常发生。但正如塞廷所说,0,0不应该被认为是在一个数组中的可能的重复范围之外
public int GetMineCount(int posY, int posX)
{
    int count = 0;
    if (GetCellState(posY-1, posX-1) == CellState.Mine)
        count++;
    if (GetCellState(posY-1, posX) == CellState.Mine)
        count++;
    if (GetCellState(posY-1, posX+1) == CellState.Mine)
        count++;
    if (GetCellState(posY, posX-1) == CellState.Mine)
        count++;
    if (GetCellState(posY, posX+1) == CellState.Mine)
        count++;
    if (GetCellState(posY+1, posX-1) == CellState.Mine)
        count++;
    if (GetCellState(posY+1, posX) == CellState.Mine)
        count++;
    if (GetCellState(posY+1, posX+1) == CellState.Mine)
        count++;
    return count;
}