【问题标题】:Accessing out of bounds cells in a 2D array访问二维数组中的越界单元格
【发布时间】:2015-10-23 15:28:56
【问题描述】:

我真的看不出我的检查邻居功能在我的生活游戏中有什么问题。它检查所有 8 个邻居,然后根据存活计数将被检查的单元格分配为存活或死亡,然后更新板。

void check_neighbours (int board[][COL])

{

int living = 0, i, j, k, l;
int new_board[ROW][COL];

for (i = 0; i < ROW; i++)
    {
    for (j = 0; j < COL; j++)
        {
        if ((board[i + 1 % ROW][j % COL]) == '#')
            {
                living++;
            }
        if ((board[i - 1 % ROW ][j % COL]) == '#')
            {
                living++;
            }
        if ((board[i % ROW][j + 1 % COL]) == '#')
            {
                living++;
            }
        if ((board[i % ROW][j - 1 % COL]) == '#')
            {
                living++;
            }
        if ((board[i + 1 % ROW][j + 1 % COL]) == '#')
            {
                living++;
            }
        if ((board[i - 1 % ROW ][j + 1 % COL ]) == '#')
            {
                living++;
            }
        if ((board[i + 1 % ROW ][j - 1 % COL ]) == '#')
            {
                living++;
            }
        if ((board[i - 1 % ROW ][j - 1 % COL ]) == '#')
            {
                living++;
            }
        if (living == 3)
            {
                new_board[i][j] = '#';
            }
        if (living <= 2)
            {
                new_board[i][j] = '-';
        if (living < 3)
            {
                new_board[i][j] = '-';
            }
        }
    }


for (k = 0; k < ROW; k++)                       
    {
    for (l = 0; l < COL; l++)                   
        {
            board[k][l] = new_board[k][l]; 
        }
    }      
}
}

编辑:添加了括号但仍然打印相同

【问题讨论】:

  • 嘿,单行不需要括号;)
  • @Kotshi 在一行中使用方括号不一定是不好的做法。
  • 运算符 % 的优先级高于运算符 +
  • @Kotshi 没有。这肯定比添加新行时忘记大括号更不烦人。
  • 请不要在回答后销毁您的问题。

标签: c arrays


【解决方案1】:

尝试在数学中添加一些括号:

board[(i + 1) % ROW]

更安全
board[i + 1 % ROW]

【讨论】:

  • 不幸的是,这仍然会打印出同样的混乱板
【解决方案2】:

在进行living 计数之前测试边缘条件。

for (i = 0; i < ROW; i++) {
    for (j = 0; j < COL; j++) {
      int living = 0;
      for (int drow = -1; drow <= 1; drow++) {
        int row = i+drow;
        if (row < 0 || row >= ROW) continue;  // over the edge
        for (int dcol = -1; dcol <= 1; dcol++) {
          int col = j+dcol; 
          if (col < 0 || col >= COL) continue;  // over the edge
          if (row==0 && col==0) continue;  
          if (board[row][col] == '#') {
            living++;
          }
        } // endfor dcol
      } // endfor drow

      // This section may need review - GOL rules are unclear in post -see below
      if (living == 3) {
        new_board[i][j] = '#';
      } 
      ...
    } // endfor j
  } // endfor i

如果遵循规则:

任何少于两个活邻居的活细胞都会死亡,好像是由于人口不足造成的。
任何有两三个活邻居的活细胞都可以活到下一代。
任何有超过三个活邻居的活细胞都会死亡,就像人口过剩一样。
任何只有三个活邻居的死细胞都会变成活细胞,就像通过繁殖一样。

     #define ALIVE ('#')
     #define DEAD  ('-')
     #define POP_MIN 2
     #define POP_MAX 3
     #define POP_REPRO 3

     new_board[i][j] = board[i][j];
     if (board[i][j] == ALIVE) {
       if (living < POP_MIN) new_board[i][j] = DEAD;
       else if (living > POP_MAX) new_board[i][j] = DEAD;
     } else {
       if (living == POP_REPRO) new_board[i][j] = ALIVE;
     }

【讨论】:

  • new_board[i][j] = board[i][j] 也应该颠倒吗?将新板复制到旧板中?如果我将它们反转,则电路板不会更新并且会充满死细胞。
  • 我知道我已经给出了正确的答案,所以您不必继续提供帮助 :)
  • 你的方法会引起一些移动,但是在游戏中进行 10000 次迭代后,滑翔机只会在相同的位置移动?
  • @Finlandia_C 可以处理生命游戏边缘条件,如上边/墙。或者,代码可以环绕。然后if (row &lt; 0 || row &gt;= ROW) continue; 变为row %= ROW; col
  • 这也行不通。我发现很难把底部的鳕鱼和顶部的鳕鱼放在一起。底部没有括号让我感到困惑
【解决方案3】:

这不是吗:

board[i + 1 % ROW]

越界?尝试解决这些问题。

正如 Paul R 所建议的那样,您可以使用括号,以便赶上 % 运算符相对于 + 运算符的更高优先级。所以把代码改成这样:

board[(i + 1) % ROW]

假设 ROW = 5 且 i = 4,您会得到:

(4 + 1) % 5 = 0 // 是的!

4 + 1 % 5 = 5 // 天哪...

【讨论】:

  • 我认为 % ROW 添加处理了这个问题?我一定是错的
  • 假设@Finlandia_C,你的ROW = 5,那么i 将得到值4,所以4 + 1 % 5 = 5,这是非法的。
  • 嗯。那么我该如何解决这个问题呢?
  • 使用括号解决运算符优先级问题。
  • 这不能解决(0 - 1) % ROW-case。
猜你喜欢
  • 2018-06-21
  • 2014-03-04
  • 2019-11-02
  • 1970-01-01
  • 2013-05-01
  • 1970-01-01
  • 2014-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多