【问题标题】:Reduce complexity of counting neighbours (Conway's Game of Life)减少计算邻居的复杂性(康威的生命游戏)
【发布时间】:2021-04-06 15:27:22
【问题描述】:

我必须实现康威的生命游戏。一切正常,并且给定的测试正在通过。我唯一的问题是,在我的文件上运行 PMD 规则时,这种方法会产生复杂性错误。我知道有很多 if 语句是造成这种情况的原因,但是在尝试将它们压缩成更小的组时,我不小心破坏了我的代码。

它是这样说的:

The method 'getNeighbourCount(int, int)' has a cyclomatic complexity of 21.

The method 'getNeighbourCount(int, int)' has an NPath complexity of 20736, current threshold is 200

优化此方法的最佳选择是什么?

public Integer getNeighbourCount(int x, int y) {
        // x = column (20), y = row (15)

        int countNeigbours = 0;
        if (x != 0 && y != 0 && isAlive(x - 1,y - 1)) {
            countNeigbours++;
        }

        if (x != 0 && isAlive(x - 1, y)) {
            countNeigbours++;
        }

        if (x != 0 && y != rows - 1 && isAlive(x - 1,y + 1)) {
            countNeigbours++;
        }
        if (y != 0 && isAlive(x,y - 1)) {
            countNeigbours++;
        }
        // check self
        if (y != rows - 1 && isAlive(x,y + 1)) {
            countNeigbours++;
        }

        if (x != columns - 1 && y != 0 && isAlive(x + 1,y - 1)) {
            countNeigbours++;
        }

        if (x != columns - 1 && isAlive(x + 1, y)) {
            countNeigbours++;
        }

        if (x != columns - 1 && y != rows - 1 && isAlive(x + 1,y + 1)) {
            countNeigbours++;
        }

        return countNeigbours;
}

isAlive 返回布尔值,如果单元格被占用(真)或不被占用(假)。

【问题讨论】:

    标签: java optimization cyclomatic-complexity


    【解决方案1】:

    从当前位置循环遍历“delta x”和“delta y”:

    for (int dx : new int[]{-1, 0, 1}) {
      if (x + dx < 0 || x + dx >= columns) continue;
    
      for (int dy : new int[]{-1, 0, 1}) {
        if (y + dy < 0 || y + dy >= rows) continue;
        if (dx == 0 && dy == 0) continue;
    
        if (isAlive(x + dx, y + dy)) countNeighbours++;
      }
    }
    

    (当然,您不必使用数组和增强的 for 循环:您可以直接使用 for (int dx = -1; dx &lt;= 1; ++dx),或者您喜欢的其他方式)

    【讨论】:

    • 谢谢你,它真的帮助了我。首先,理解起来很棘手,但在调试我的代码时它是有道理的:)
    【解决方案2】:

    我不知道这是否会加快速度,但您可以尝试使用第二个数组来保存总和,并在设置或清除单个单元格时增加或减少这些值。这用检查是否应该打开或关闭单元格来替换许多“isAlive”检查,并将单元格邻接计算减少到仅被切换的那些单元格,这应该比对整个数组重复计算要少得多.也就是说,对于一个大部分为空的网格,只有一小部分单元格需要重新计算,比整个网格要少得多。

    另外,您可以尝试使用整行 isActiveminActivemaxActive 值。这将进一步减少循环的数量,但会增加每次迭代的复杂性和成本。活动单元的稀疏性将决定额外成本是否与迭代次数的减少相平衡。

    【讨论】:

      猜你喜欢
      • 2023-03-28
      • 2019-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-13
      • 1970-01-01
      • 1970-01-01
      • 2010-09-07
      相关资源
      最近更新 更多