【问题标题】:Wrapping around a grid with modulo用模环绕网格
【发布时间】:2015-09-18 17:09:11
【问题描述】:

我正在尝试编写一个程序,在 20x60 单元格的网格上实现康威的生命游戏。网格应该环绕,以便左侧连接到右侧,顶部连接到底部。

因此,任何位置为(0, col) 的单元格都将在(maxRow, col) 处有一个邻居。任何位置为(row, 0) 的单元格都将在(row, maxCol) 处有一个邻居。

下面的函数应该计算相邻单元格的数量。它适用于不在边缘的坐标,但不适用于边缘的坐标。例如,如果将(0, 10)(0, 11)(0, 12)(0, 10) 处的点传递给函数,它将返回一个高数字作为邻居计数而不是1。我知道 mod 运算符 % 会有所帮助,但我不明白如何使用它。

{
    int i, j;
    int count = 0;
    for (i = row - 1; i <= row + 1; i++)
       for (j = col - 1; j <= col + 1; j++) 
           count += grid[i][j]; }

    if (row==maxrow-1 || row==0)
         count = count+ grid [(row-(maxrow-1))*-1][col-1]+grid[(row-(maxrow-1))*-1][col]+grid[(row-(maxrow-1))*-1][col+1];

    if (col==0 || col==maxcol-1)
         count=count +grid[row-1][(col-(maxcol-1))*-1]+grid[row][(col-(maxcol-1))*-1]+grid[row+1][(col-(maxcol-1))*-1];



    count -= grid[row][col];
    return count;
    } 

【问题讨论】:

    标签: c++ algorithm modulo cellular-automata


    【解决方案1】:

    在提供解决方案之前,让我做一些观察。

    • 将一些网格值相加然后再减去其他网格值并不是一个好主意。您应该首先计算正确的网格坐标。

    • 当您编写 count += grid[i][j]; 时,您使用的数组索引可能无效。例如,当row 为零时,i = row - 1 产生的i 值为-1

    • 您的代码暗示 maxrow 是行数,因为您正在编写 maxrow-1,但名称 maxrow 暗示了最大行索引。这令人困惑。最好将行数称为numRows,然后最大行索引为numRows - 1。同样,最好将maxcol 替换为numCols

    现在进入问题的核心。值row - 1 可以等于-1row + 1 可以等于numRows。这两个都是无效的行索引。同样,col - 1col + 1 会导致无效的列索引 -1numCols。解决问题的一种方法是测试这些特定值并用环绕索引替换它们:

    int count = 0;
    for (int i = row - 1; i <= row + 1; i++) {
      int R = i;
      if (R == -1) {
        R = numRows - 1;
      } else if (R == numRows) {
        R = 0;
      }
      for (int j = col - 1; j <= col + 1; j++) {
        if (i == row && j == col) {
          continue;  // Skip grid[row][col].
        }
        int C = j;
        if (C == -1) {
          C = numCols - 1;
        } else if (C == numCols) {
          C = 0;
        }
        count += grid[R][C];
      }
    }
    

    这是解决问题的一种高性能方法,因为测试和赋值是比模运算更快的运算,但它也需要大量代码。我们可以借助模运算符编写更简洁的代码。

    我们想写i % numRows,除了当i 为-1 时C++ 将其计算为-1。这是因为模运算对于负值是不明确的,C++ has chosen an interpretation 不能保证非负结果。

    为了解决这个问题,我们在取模 numRows 之前将 numRows 添加到 i。这确保我们总是取正数的模。现在我们可以统计grid[row][col]的八个邻居中活细胞的数量,如下所示。

    int count = 0;
    for (int i = row - 1; i <= row + 1; i++) {
      for (int j = col - 1; j <= col + 1; j++) {
        if (i == row && j == col) { 
          continue;  // Skip grid[row][col].
        }
        count += grid[(i + numRows) % numRows][(j + numCols) % numCols];
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-14
      • 1970-01-01
      • 2010-12-21
      • 1970-01-01
      相关资源
      最近更新 更多