如何迭代点(x,y)上的序数方向?

时间:2016-06-02 16:48:04

标签: java refactoring

我在下面有这个函数叫做findNeighboringChains(i,j)。传入一个点(x,y),它返回存在于相邻点(x + 1,y),(x - 1,y),(x,y + 1)和(x, y - 1)。如果(x,y)处不存在链,则findChainId(x,y)= -1,否则它将返回ID> = 0.每个(x,y)只能存在一个链。有关更多上下文,这是我在Go游戏中用于查找单元格的相邻链的函数。

我觉得到目前为止我所拥有的有点冗长,但我不确定如何让它变得更好。如果我可以通过循环迭代这些点(x + 1,y)...(x,y - 1),这似乎是理想的。有什么建议吗?

public ArrayList<Integer> findNeighboringChains(int i, int j) {
    ArrayList<Integer> neighboringChains = new ArrayList<>();

    int tmp = findChainId(i - 1, j);
    if (tmp != -1) {
        neighboringChains.add(tmp);
    }

    tmp = findChainId(i + 1, j);
    if (tmp != -1) {
        neighboringChains.add(tmp);
    }

    tmp = findChainId(i, j - 1);
    if (tmp != -1) {
        neighboringChains.add(tmp);
    }

    tmp = findChainId(i, j + 1);
    if (tmp != -1) {
        neighboringChains.add(tmp);
    }

    return neighboringChains;
}

1 个答案:

答案 0 :(得分:2)

一种方法是利用内置于Java中的Point对象,并迭代一个点列表 - 每次调用同一段代码。在我的解决方案/重构中,我创建了一个名为“getNeighboringPoints(Point p)”的新方法,该方法检索四个相邻点。然后,在你的函数findNeighboringChains中,你可以在点列表上使用for-each循环进行迭代。

你可以做的这种模式有很多变化,但你认为可以减少冗余是绝对正确的。尝试遵循DRY原则始终是一个好主意。

public ArrayList<Integer> findNeighboringChains(int i, int j) {
    ArrayList<Integer> neighboringChains = new ArrayList<>();

    Point p = new Point(i, j);
    List<Point> neighboringPoints = getNeighboringPoints(p);

    for (Point point : neighboringPoints) {
        int tmp = findChainId(point.x, point.y);
        if (tmp != -1) {
            neighboringChains.add(tmp);
        }
    }

    return neighboringChains;
}

/**
 * 
 * @param p
 *            The input point.
 * @return a list of points neighboring point p
 */
private List<Point> getNeighboringPoints(Point p) {
    ArrayList<Point> neighboringPoints = new ArrayList<Point>();
    neighboringPoints.add(new Point(p.x - 1, p.y));
    neighboringPoints.add(new Point(p.x + 1, p.y));
    neighboringPoints.add(new Point(p.x, p.y + 1));
    neighboringPoints.add(new Point(p.x, p.y - 1));
    return neighboringPoints;
}

上述方法的一个好处是,现在您可以在以后发现可能需要对所有相邻点执行另一个操作,并且可以重用方法getNeighboringPoints()。

编辑:

减少冗余的另一种方法是使用extract method技术。

public ArrayList<Integer> findNeighboringChains(int i, int j) {
    ArrayList<Integer> neighboringChains = new ArrayList<>();

    int tmp = findChainId(i - 1, j);
    checkChain(neighboringChains, tmp);

    tmp = findChainId(i + 1, j);
    checkChain(neighboringChains, tmp);

    tmp = findChainId(i, j - 1);
    checkChain(neighboringChains, tmp);

    tmp = findChainId(i, j + 1);
    checkChain(neighboringChains, tmp);

    return neighboringChains;
}

private void checkChain(ArrayList<Integer> neighboringChains, int tmp) {
    if (tmp != -1) {
        neighboringChains.add(tmp);
    }
}

这可能会更好,因为它不会强制在已经不使用点的项目上使用点类。 (当有一种方法使用其他一切需要输入两个整数的点时,可能会很烦人。)