【问题标题】:How to avoid accessing an invalid position in a 2d array?Java - 如何避免访问二维数组中的无效位置?
【发布时间】:2021-10-28 18:51:53
【问题描述】:

我正在研究 Knight's Tour 问题,我正在为它制定一个递归解决方案。 https://www.chess.com/terms/knights-tour-chess#:~:text=The%20knight's%20tour%20is%20a,same%20square%20more%20than%20once.

我有一个矩阵[8][8] 和一个名为knightMove(int currentRow, int currentColumn); 的方法 这个方法应该将骑士可以从当前位置进行的所有可能的移动添加到一个数组中。如果可能移​​动的位置值等于 0,则从新位置再次调用 knightMove(newRow, newColumn)

如果它找到了一个死路,那么它将在前一次调用中尝试数组中的下一个可能移动,如果它用完之前的数组位置,那么它将尝试在此之前调用的数组中的下一个位置,依此类推。该程序只有在找到问题的正确解决方案时才会结束。

现在我的问题来了,我想避免使用这么多“if”来检查骑士移动是否超出桌面。

    ArrayList <int[]> moves = new ArrayList<int[]>();
    int[] arr = new int[2];
    int max=8;
    if (currentColumn-2 > 0){
        
        if(currentRow - 1 > 0){
            arr[0] = currentColumn-2;
            arr[1] = currentRow-1;  
            moves.add(arr);
        } 
        
        if(currentRow+1 < max){
            arr[0] = currentColumn-2;
            arr[1] = currentRow+1;
            moves.add(arr);
        }
    } 
   if (currentRow-2 > 0){
        
        if(currentColumn-1 > 0){                
            arr[0] = currentColumn-1;  
            arr[1] = currentRow-2;
            moves.add(arr);  
        } 
        
        if(currentColumn+1 < max){
            arr[0] = currentColumn+1;
            arr[1] = currentRow-2;
            moves.add(arr);
        }
    } 
    if (currentColumn+2 > 0){
        
        if(currentRow-1 > 0){
            arr[0] = currentColumn+2;
            arr[1] = currentRow-1;  
            moves.add(arr);
        } 
        
        if(currentRow+1 < max){
            arr[0] = currentColumn+2;
            arr[1] = currentRow+1;
            moves.add(arr);
        }
    } 
    if (currentRow+2 > 0){
       
        if(currentColumn-1 > 0){
            arr[0] = currentColumn-1;  
            arr[1] = currentRow+2;
            moves.add(arr);
        } 
       
        if(currentRow+1 < max){
            arr[0] = currentColumn+2;
            arr[1] = currentRow+1;
            moves.add(arr);
        }
    } 

     for (int[] c : moves){
     // recursive logic...
     }

我对无效位置不感兴趣,如果编译器无法访问这些无效位置,那么就不要对它们做任何事情,不要破坏我的代码,专注于那些真正有效的位置。我想做类似下面的事情,仅在数组中添加有效位置的值(utopic 解决方案):

int[] temp = {
            table[currentRow-2][currentColumn-1], 
            table[currentRow-2][currentColumn+1], 
            table[currentRow+1][currentColumn-2], 
            table[currentRow-1][currentColumn-2],  
            table[currentRow+2][currentColumn-1], 
            table[currentRow+2][currentColumn+1], 
            table[currentRow-1][currentColumn+2], 
            table[currentRow+1][currentColumn+2]  
        };

我想帮助找出一种更好的方法来避免访问矩阵中的无效位置。

【问题讨论】:

  • 有些东西必须对其进行测试。如果必须发生。你的选择只是你想湿还是干。 DRY 方法是隔离坐标测试:创建一个测试坐标的函数,如果有效,则将坐标处的值添加到数组列表中。然后在一个空的数组列表上调用该函数八次。

标签: java arrays recursion matrix


【解决方案1】:

这是我的许多测试运行之一的结果。

Origin row: 3, column: 4
    Move to row: 1, column: 5
    Move to row: 1, column: 3
    Move to row: 2, column: 6
    Move to row: 2, column: 2
    Move to row: 4, column: 6
    Move to row: 4, column: 2
    Move to row: 5, column: 5
    Move to row: 5, column: 3

Origin row: 1, column: 1
    Move to row: 0, column: 3
    Move to row: 2, column: 3
    Move to row: 3, column: 2
    Move to row: 3, column: 0

Origin row: 7, column: 7
    Move to row: 5, column: 8
    Move to row: 5, column: 6
    Move to row: 6, column: 5
    Move to row: 8, column: 5

Origin row: 1, column: 7
    Move to row: 0, column: 5
    Move to row: 2, column: 5
    Move to row: 3, column: 8
    Move to row: 3, column: 6

Origin row: 7, column: 1
    Move to row: 5, column: 2
    Move to row: 5, column: 0
    Move to row: 6, column: 3
    Move to row: 8, column: 3

我做的第一件事是创建一个Coordinate 类。这使我可以将索引越界测试放在Coordinate 类中的一处。

knightMove 方法计算出有多少移动是有效的,创建一个 Coordinates 数组,并返回有效的移动坐标。

这是完整的、可运行的代码。

public class MoveKnight {

    public static void main(String[] args) {
        MoveKnight mk = new MoveKnight();
        displayOutput(mk, 3, 4);
        displayOutput(mk, 1, 1);
        displayOutput(mk, 7, 7);
        displayOutput(mk, 1, 7);
        displayOutput(mk, 7, 1);
    }

    private static void displayOutput(MoveKnight mk, int row, int column) {
        System.out.println("Origin row: " + row + ", column: " + column);
        Coordinate[] output = mk.knightMove(row, column);
        for (int index = 0; index < output.length; index++) {
            System.out.println("    Move to row: " + output[index].getRow() + 
                    ", column: " + output[index].getColumn());
        }
        System.out.println();
    }

    public Coordinate[] knightMove(int currentRow, int currentColumn) {
        Coordinate[] difference = { new Coordinate(-2, 1), new Coordinate(-2, -1), 
                new Coordinate(-1, 2), new Coordinate(-1, -2), new Coordinate(1, 2), 
                new Coordinate(1, -2), new Coordinate(2, 1), new Coordinate(2, -1) };

        int count = 0;
        for (int index = 0; index < difference.length; index++) {
            Coordinate destination = new Coordinate(currentRow, currentColumn);
            destination.incrementCoordinate(difference[index]);
            if (destination.isValid()) {
                count++;
            }
        }

        Coordinate[] output = new Coordinate[count];
        count = 0;
        for (int index = 0; index < difference.length; index++) {
            Coordinate destination = new Coordinate(currentRow, currentColumn);
            destination.incrementCoordinate(difference[index]);
            if (destination.isValid()) {
                output[count++] = destination;
            }
        }

        return output;
    }

    public class Coordinate {

        private int column, row;

        public Coordinate(int row, int column) {
            setRowColumn(row, column);
        }

        public int getColumn() {
            return column;
        }

        public int getRow() {
            return row;
        }

        public void incrementCoordinate(Coordinate increment) {
            this.row += increment.getRow();
            this.column += increment.getColumn();
        }

        public void setRowColumn(int row, int column) {
            this.row = row;
            this.column = column;
        }

        public boolean isValid() {
            return row >= 0 && row < 8 && column >= 0 && column < 8;
        }

    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 2011-02-12
    • 2021-10-11
    • 2020-06-04
    • 2011-09-27
    • 2012-04-17
    • 1970-01-01
    相关资源
    最近更新 更多