简体   繁体   中英

Finding the diagonal edges of an 2D array relative to any position - Java

I have a 6x6 array of numbers:

        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}
    };

If my starting position is multi[2][3] . How can I find the diagonal edges of the array relative to that value? For example, at point multi[2][3] the value is 7. The diagonal should be points multi[0][1] , multi[0][5] , multi[4][5] , and multi[5][0] . Here is what my code currently does:

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

This method then eliminates the impossible values:

    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;
}

Lastly, this method eliminates all the moves that aren't on the edges of the array.

    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;
}

Running this program results in the following which is not correct.

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]]

What is the simplest way to find the diagonals of any random point in a square 2D array? Also, suggestions on how to streamline my code would be greatly appreciated.

Thanks!

A number is on an edge of a square if one of the indices is equal to 0, or the length/height of the array. Assuming the array is already a square (you can do the check yourself):

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

Assuming you have the x and y coordinates of the original point:

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
}

But wait, do we really need a loop? What if we just straight up add a certain value to the x and y points to reach the edge in 1 step? How do we do that?

Take (2, 3) for example (value = 7 in your array). To find the (0, 0) corner, we use this logic:

  • x = 2 is closer to 0 than y is closer to 0 so we get (x - x, y - x) = (0, 1)
  • this applies if y is closer to 0 than x: (x - y, y - y) = (x - y, 0)

Take this and apply to say, the (length, height) corner:

  • (y = 3) is closer to (height = 5) than (x = 2) to (length = 5) so we get (x + (height - y), (y + (height - y)) = (4, 5)

All 4 corners translated to code would be:

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;
}

Which can be cleaned up to:

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;
}

I'd do it much more directly. As long as we're supposing that multi is regular, not ragged, we don't even need to know beforehand what its dimensions are. It doesn't even need to be square.

For example, this approach is a much more succinct version of yours:

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));
    }

    // ...
}

Note in particular that we can know which points are on an edge very easily (as shown). You can wrap the given condition in a method if you prefer, but there's not much to it. Either way, there's no special need to create Point s that we know are not on an edge, or to engage in two rounds of filtering, or any of that stuff.

Note also that I have DRYed out your code by introducing the directions array. The operations you perform to handle each direction are the same, but for the increments (+1 or -1) for the two axes. The elements of direction capture those differences, removing the need for repetitious code.

Finally, do note that if the initial position is on an edge then two of the computed "moves" will leave the piece at its initial position, and if the initial position is in a corner then three of the moves will leave it in the same place. You can eliminate those, if you wish, by testing x1 and / or y1 before adding a move to finalMoves . Of course, if you do that then the result will sometimes contain fewer than four moves.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM