【问题标题】:How can the logic of this snippet be abstracted?这个片段的逻辑怎么抽象?
【发布时间】:2012-03-21 10:06:10
【问题描述】:

下面的方法用于判断棋子是否被阻止进行某步棋。在调用此方法时,运动本身(即主教沿对角线移动的能力)已经得到验证——然后此方法将查看棋子必须采用的“路径”。

很清楚,这种方法充满了冗余。实际上,有 6 个几乎相同的 for 循环,区别在于 1) 哪些变量控制迭代,2) 变量是递增还是递减,以及 3) 在对角线运动的情况下,包含同时增加/减少 x 和 y 变量的语句。

我已经多次尝试将这些语句抽象为一个单独的方法。不幸的是,限制因素是需要访问 board[y][x] - 当我尝试抽象逻辑时,我看不到 which 变量代表 y 和哪个 x .

那么,我的问题是:Java 可以为我提供哪些工具来抽象此逻辑并减少或消除此方法中的冗余?我会指出我对这门语言很陌生,所以请不要把我对常见习语的漠视视为故意或只是迟钝;我正在学习!

谢谢。

private static boolean notBlocked(Piece[][] board, int xfrom, int yfrom, int xto, int yto) {

    int x = xfrom;
    int xstop = xto;
    int y = yfrom;
    int ystop = yto;

    int xinc = (x < xstop) ? 1 : -1;
    int yinc = (y < ystop) ? 1 : -1;

    Piece to = board[yto][xto];
    Piece from = board[yfrom][xfrom];

    if (xfrom == xto) {
        // x is constant, check in y direction
        if (y <= ystop) {
            for (; y <= ystop; y += yinc) {
                if (board[y][x] != null && board[y][x] != to && board[y][x] != from) {
                    return false;
                }
            }
        } else {
            for (; y >= ystop; y += yinc) {
                if (board[y][x] != null && board[y][x] != to && board[y][x] != from) {
                    return false;
                }
            }
        }
    } else if (yfrom == yto) {
        // y is constant, check in x direction
        if (x <= xstop) {
            for (; x <= xstop; x += xinc) {
                if (board[y][x] != null && board[y][x] != to && board[y][x] != from) {
                    return false;
                }
            }
        } else {
            for (; x >= xstop; x += xinc) {
                if (board[y][x] != null && board[y][x] != to && board[y][x] != from) {
                    return false;
                }
            }
        }
    } else if (Math.abs(xfrom - xto) == Math.abs(yfrom - yto)){
        // the move is diagonal
        if (y <= ystop) {
            for (; y <= ystop; y += yinc) {
                if (board[y][x] != null && board[y][x] != to && board[y][x] != from) {
                    return false;
                }
                x += xinc;
            }
        } else {
            for (; y >= ystop; y += yinc) {
                if (board[y][x] != null && board[y][x] != to && board[y][x] != from) {
                    return false;
                }
                x += xinc;
            }
        }
    }
    return true;
}

编辑:

哇……现在好多了!

private static boolean notBlocked(Piece[][] board, int xfrom, int yfrom, int xto, int yto) {

    Piece from = board[yfrom][xfrom];
    Piece to = board[yto][xto];

    // Determine the direction (if any) of x and y movement
    int dx = (xfrom < xto) ? 1 : ((xfrom == xto) ? 0 : -1);
    int dy = (yfrom < yto) ? 1 : ((yfrom == yto) ? 0 : -1);

    // Determine the number of times we must iterate
    int steps = Math.max(Math.abs(xfrom - xto), Math.abs(yfrom - yto));

    if (xfrom == xto || yfrom == yto || Math.abs(xfrom - xto) == Math.abs(yfrom - yto)) {
        for (int i = 1; i < steps; i++) {
            int x = xfrom + i * dx;
            int y = yfrom + i * dy;
            if (isBlocked(board, from, to, x, y)) {
                return false;
            }
        }
    }
    return true;
}

【问题讨论】:

    标签: java arrays for-loop boolean


    【解决方案1】:

    考虑朝着正确的方向迈出一步来编写这个函数。假设您可以填写两个变量 dx 和 dy,它们分别代表您在每一步中沿 x 和 y 方向移动了多少。您可以通过查看开始和结束 x 和 y 位置之间的差异来计算它。一旦你有了它,你就可以编写一个 for 循环,尝试沿着那个方向移动,检查每一步。例如:

    for (int i = 1; i < numStepsRequired; i++) {
        int currX = x + i * dx;
        int currY = y + i * dy;
        if (board[currY][currX] != null) {
            return false;
        }
    }
    

    您还需要计算需要多少步,只要您计算 dx 和 dy,这也很简单。我将把它留作练习,因为它是很好的编程习惯。

    希望这会有所帮助!

    【讨论】:

    • 谢谢!这是一个明显优越的观点。我很欣赏这个方向。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 1970-01-01
    • 2011-01-26
    • 2012-05-18
    • 2023-03-18
    • 1970-01-01
    相关资源
    最近更新 更多