【问题标题】:Finding the diagonal edges of an 2D array relative to any position - Java查找相对于任何位置的二维数组的对角线边缘 - Java
【发布时间】:2016-07-19 20:59:00
【问题描述】:

我有一个 6x6 的数字数组:

        int[][] multi = new int[][]{
        {4, 2, 3, 2, 5, 1},
        {2, 5, 5, 4, 1, 1},
        {2, 4, 6, 7, 2, 4},
        {2, 1, 2, 3, 4, 3},
        {3, 5, 1, 4, 5, 2},
        {1, 2, 1, 4, 1, 2}
    };

如果我的起始位置是multi[2][3]。如何找到数组相对于该值的对角线边缘?例如,点 multi[2][3] 的值为 7。对角线应为点 multi[0][1]multi[0][5]multi[4][5]multi[5][0]。这是我的代码目前所做的:

if (LocationValue == 7) {//find possible moves
            //There should be 4 potential moves

            ArrayList<Point> Moves = new ArrayList<Point>();
            Point DMove;

            for (int i = 0; i < multi.length; i++) {
                DMove = new Point(x + i, y + i);
                Moves.add(new Point(DMove));
            }
            for (int i = 0; i < multi.length; i++) {
                DMove = new Point(x - i, y + i);
                Moves.add(new Point(DMove));
            }
            for (int i = 0; i < multi.length; i++) {
                DMove = new Point(x - i, y - i);
                Moves.add(new Point(DMove));
            }
            for (int i = 0; i < multi.length; i++) {
                DMove = new Point(x + i, y - i);
                Moves.add(new Point(DMove));
            }

            ArrayList<Point> AlmostFinalMoves = FindPossibleMoves(Moves); //eliminate impossible moves
            ArrayList<Point> FinalMoves = FindSideMoves(AlmostFinalMoves, x, y); //Get bishop moves
            System.out.println("Possible Moves: " + FinalMoves);

          }//End of IF

然后这个方法消除了不可能的值:

    public static ArrayList<Point> FindPossibleMoves(ArrayList<Point> AllMoves) {

    ArrayList<Point> FinalMoves = new ArrayList<Point>();

    for (int i = 0; i < AllMoves.size(); i++) {

        if (AllMoves.get(i).getX() >= 0 && AllMoves.get(i).getX() <= 5 && AllMoves.get(i).getY() >= 0 && AllMoves.get(i).getY() <= 5) {
            FinalMoves.add(AllMoves.get(i));
        }
    }

    return FinalMoves;
}

最后,这个方法消除了所有不在数组边缘的移动。

    public static ArrayList<Point> FindSideMoves(ArrayList<Point> AllPossibleMoves, int xloc, int yloc) {

    ArrayList<Point> AlmostFinalSideMoves = new ArrayList<Point>();
    ArrayList<Point> FinalSideMoves = new ArrayList<Point>();

    for (int i = 0; i < AllPossibleMoves.size(); i++) {

        if (AllPossibleMoves.get(i).getX() == 0) {
            if (AllPossibleMoves.get(i).getY() == 0 || AllPossibleMoves.get(i).getY() == 1 || AllPossibleMoves.get(i).getY() == 2 || AllPossibleMoves.get(i).getY() == 3 || AllPossibleMoves.get(i).getY() == 4 || AllPossibleMoves.get(i).getY() == 5) {
                AlmostFinalSideMoves.add(AllPossibleMoves.get(i));
            }
        }
        if (AllPossibleMoves.get(i).getX() == 5) {
            if (AllPossibleMoves.get(i).getY() == 0 || AllPossibleMoves.get(i).getY() == 1 || AllPossibleMoves.get(i).getY() == 2 || AllPossibleMoves.get(i).getY() == 3 || AllPossibleMoves.get(i).getY() == 4 || AllPossibleMoves.get(i).getY() == 5) {
                AlmostFinalSideMoves.add(AllPossibleMoves.get(i));
            }
        }
        if (AllPossibleMoves.get(i).getX() == 1) {
            if (AllPossibleMoves.get(i).getY() == 0 || AllPossibleMoves.get(i).getY() == 5) {
                AlmostFinalSideMoves.add(AllPossibleMoves.get(i));
            }
        }
        if (AllPossibleMoves.get(i).getX() == 2) {
            if (AllPossibleMoves.get(i).getY() == 0 || AllPossibleMoves.get(i).getY() == 5) {
                AlmostFinalSideMoves.add(AllPossibleMoves.get(i));
            }
        }
        if (AllPossibleMoves.get(i).getX() == 3) {
            if (AllPossibleMoves.get(i).getY() == 0 || AllPossibleMoves.get(i).getY() == 5) {
                AlmostFinalSideMoves.add(AllPossibleMoves.get(i));
            }
        }
        if (AllPossibleMoves.get(i).getX() == 4) {
            if (AllPossibleMoves.get(i).getY() == 0 || AllPossibleMoves.get(i).getY() == 5) {
                AlmostFinalSideMoves.add(AllPossibleMoves.get(i));
            }
        }
    }

    for (int i = 0; i < AlmostFinalSideMoves.size(); i++) {//Check to see if any possible moves match the original location. If so, do not include in list
        if (AlmostFinalSideMoves.get(i).getX() == xloc && AlmostFinalSideMoves.get(i).getY() == yloc) {
            //Do Nothing!
        } else {
            FinalSideMoves.add(AlmostFinalSideMoves.get(i));
        }
    }

   return FinalSideMoves;
}

运行此程序会导致以下不正确的结果。

Possible Moves: [java.awt.Point[x=0,y=3], java.awt.Point[x=0,y=5], java.awt.Point[x=2,y=5], java.awt.Point[x=4,y=5], java.awt.Point[x=5,y=3], java.awt.Point[x=5,y=0], java.awt.Point[x=2,y=0], java.awt.Point[x=0,y=1]]

在正方形二维数组中找到任意随机点的对角线的最简单方法是什么?此外,我们将不胜感激有关如何简化我的代码的建议。

谢谢!

【问题讨论】:

  • 你的索引符号很奇怪。您说 (3,2) 处的点值为 7,但 multi[3][2] 的值为 2。multi[2][3] 的值为 7。这也是我直接处理数据的方式。如果您使用 Java 表示法,或者至少使用与 Java 表示法中的顺序一致的索引顺序,也许我们都会变得更好。
  • 你是绝对正确的。 java 使用的符号对我来说并不完全直观。我还在适应它。我将编辑我的帖子以使其更加清晰。
  • 注意左边对角线的第一个坐标如何以 0 结尾。在右侧它们以 5 结尾。你可以通过像while( (firstCoord != 0) || (secondCoord != 0)){ firstCoord--; secondCoord--; } 这样的操作找到左上角坐标,这只是一个问题减法或加法以在任一极端上获得正确的坐标。我会将您的数组和坐标传递给某种方法以获取结果值

标签: java arrays matrix 2d


【解决方案1】:

如果索引之一等于 0 或数组的长度/高度,则数字位于正方形的边缘。假设数组已经是一个正方形(你可以自己做检查):

int length = grid.length;
int height = grid[0].length;

假设你有原点的 x 和 y 坐标:

List<Point> findPossibleMoves(int x, int y) {
    int length = grid.length;
    int height = grid[0].length;
    int originalX = x;
    int originalY = y;
    //add (1, 1), (-1, 1), (-1, -1), (1, -1) to the original position until you reach an edge
}

但是等等,我们真的需要一个循环吗?如果我们直接将某个值添加到 x 和 y 点以在 1 步中到达边缘怎么办?我们如何做到这一点?

以 (2, 3) 为例(数组中的值 = 7)。为了找到 (0, 0) 角,我们使用以下逻辑:

  • x = 2 比 y 更接近 0,因此我们得到 (x - x, y - x) = (0, 1)
  • 这适用于 y 比 x 更接近 0 的情况:(x - y, y - y) = (x - y, 0)

把这个应用到说,(长度,高度)角:

  • (y = 3) 比 (x = 2) 更接近 (height = 5),所以我们得到 (x + (height - y), (y + (height - y))) = (4, 5)

所有 4 个角都转换为代码:

List<Point> findPossibleMoves(int x, int y) {
    List<Point> pointList = new ArrayList<Point>();
    int length = grid.length;
    int height = grid[0].length;

    pointList.add(new Point(x - Math.min(x, y), y - Math.min(x, y)));
    pointList.add(new Point(x + Math.min(length - x, y), y - Math.min(length - x, y)));
    pointList.add(new Point(x - Math.min(x, height - y), y + Math.min(x, height - y)));
    pointList.add(new Point(x + Math.min(length - x, height - y), y + Math.min(length - x, height - y)));

    return pointList;
}

哪些可以清理:

List<Point> findPossibleMoves(int x, int y) {
    List<Point> pointList = new ArrayList<Point>();
    int length = grid.length;
    int height = grid[0].length;

    int to00 = Math.min(x, y);
    int toL0 = Math.min(length - x, y);
    int to0H = Math.min(x, height - y);
    int toLH = Math.min(length - x, height - y);
    pointList.add(new Point(x - to00, y - to00));
    pointList.add(new Point(x + toL0, y - toL0));
    pointList.add(new Point(x - to0H, y + to0H));
    pointList.add(new Point(x + toLH, y + toLH));

    return pointList;
}

【讨论】:

    【解决方案2】:

    我会更直接地这样做。只要我们假设multi 是规则的,而不是衣衫褴褛的,我们甚至不需要事先知道它的尺寸是多少。它甚至不需要是方形的。

    例如,这种方法是您的更简洁的版本:

    if (LocationValue == 7) {
        int maxRow = multi.length - 1;
        int maxColumn = multi[0].length - 1;
        int[][] directions = { { 1, 1 }, { 1, -1 }, { -1, 1}, { -1, -1 } };
        ArrayList<Point> finalMoves = new ArrayList<>();
    
        for (int[] direction : directions) {
            int x1 = x;
            int y1 = y;
    
            // Proceed in the current direction until we reach an edge
            while (true) {
                int x2 = x1 + direction[0];
                int y2 = y1 + direction[1];
    
                if ((x2 < 0) || (x2 > numColumns)
                        || (y2 < 0) || (y2 > numRows)) {
                    // Moving in farther would take the piece off the board
                    break;
                } else {
                    x1 = x2;
                    y1 = y2;
                }
            }
    
            finalMoves.add(new Point(x1, y1));
        }
    
        // ...
    }
    

    请特别注意,我们可以很容易地知道哪些点在边上(如图所示)。如果您愿意,您可以将给定的条件包装在一个方法中,但它并没有太多。无论哪种方式,都没有特别需要创建我们知道不在边缘的Points,或者进行两轮过滤,或任何类似的东西。

    还请注意,我已经通过引入 directions 数组干掉了您的代码。您为处理每个方向执行的操作是相同的,但对于两个轴的增量(+1 或 -1)。 direction 的元素捕捉了这些差异,无需重复代码。

    最后,请注意,如果初始位置在边上,则计算出的两个“移动”将使棋子留在其初始位置,如果初始位置在角落,则三个移动将离开它在同一个地方。如果您愿意,您可以通过测试x1 和/或y1 来消除这些,然后再向finalMoves 添加移动。当然,如果你这样做,那么结果有时会包含少于四步。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 2020-03-19
      • 1970-01-01
      • 1970-01-01
      • 2016-07-23
      • 2020-07-24
      相关资源
      最近更新 更多