Java - 2D数组操作正在影响索引的反转

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java - 2D数组操作正在影响索引的反转相关的知识,希望对你有一定的参考价值。

我正在尝试通过运用我的知识和制作Java国际象棋游戏来学习Java。目前它是严格的文本。在我的程序中,我有一个功能,允许我移动一块。所有部件都存储在称为板的2D阵列中。然而问题在于当我试图移动一块时这个功能。如果我将一块(“白嘴鸦”)从board[7][0]移动到board[6][0]由于某种原因,其中相反的(board[0][0]board[1][0])也会被移动。

这是没有任何修改显示与displayBoard()的董事会:

ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK, 
PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, 
null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, 
PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, 
ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK,

一块一块地被移动:

null, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK, 
ROOK, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, 
null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, 
ROOK, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, 
null, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK, 

只有左下方的车应该被移动。 Board.Java类:

public class Board {
    public Pieces[][] board = new Pieces[8][8];

    private Pieces[] MainLine = new Pieces[]{Pieces.ROOK, Pieces.KNIGHT, Pieces.BISHOP, Pieces.QUEEN, Pieces.KING, Pieces.BISHOP, Pieces.KNIGHT, Pieces.ROOK};
    private Pieces[] BishopLine = new Pieces[]{Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN};

    public Board(){
        resetBoard();
    }

    private void resetBoard() {
        board = new Pieces[8][8];
        board[0] = MainLine;
        board[board.length - 1] = MainLine;
        board[1] = BishopLine;
        board[board.length - 2] = BishopLine;
    }

    public void displayBoard() {
        for(int rank = 0; rank < board.length; rank++) {
            System.out.println("");
            for(int file = 0; file < board.length; file ++) {
                System.out.print(board[rank][file] + ", ");
            }
        }
        for(int x = 0; x < 3; x++) {
            System.out.println("");
        }
    }

    public Pieces getPiece(int rank, int file) {
        return board[rank][file];
    }

    public void movePiece(int rank, int file, int newRank, int newFile) {
        Pieces temp = getPiece(rank, file);
        board[rank][file] = null;
        board[newRank][newFile] = temp;
    }
}

在我的主类我创建一个新的板实例,显示它,移动一块movePiece(7, 0, 6, 0),然后再次显示板。我认为主要问题是在Board.java类中,我不知道出了什么问题或为什么其他索引受到影响。任何人都可以向我解释为什么会发生这种情况或如何更好地操纵2D board阵列以进一步实现我的目标,即将一块移动到给定位置而不影响任何其他部分。

编辑:添加了额外的代码 -

Main.Java创建了一个游戏实例,其中将来会出现其他条件,但它是Game.java,它直接引用Board.Java,因为它继承了它:

public class Main {
    public static void main(String[] args) {
        Game game = new Game();

        game.displayBoard();
        game.movePiece(7, 0, 6, 0);
        game.displayBoard();

    }
}

Game.java只是调用super来创建板。它稍后会保留额外的功能:

public class Game extends Board {
    public Game() {
        super();
    }

}
答案

问题出在Board的构造函数中,更具体地说是resetBoard()方法,您将第一行初始化为与最后一行相同的数组,同样,第二行引用与第二行相同的数组:

private void resetBoard() {
    board = new Pieces[8][8];

    // board[0] is a reference to MainLine so if we change move
    // into or out of board[0] MainLine will be affected and 
    // we won't be able to start with a fresh board by calling boardReset()
    // board[0] = MainLine;

    // Initialize the first row to a fresh array every time we call
    // reset.
    board[0] = new Pieces[] { 
        Pieces.ROOK, Pieces.KNIGHT, Pieces.BISHOP, Pieces.QUEEN, 
        Pieces.KING, Pieces.BISHOP, Pieces.KNIGHT, Pieces.ROOK
    };

    // This makes the last line and
    // the first line point to the same array
    // You need to create a new array that is a deep copy
    // of the array.
    // board[board.length - 1] = MainLine; 

    // Create new array by copying the original array
    board[board.length - 1] = Arrays.copyOf(board[0], board[0].length);

    // Similarly
    //board[1] = BishopLine;
    Arrays.fill(board[1], Pieces.PAWN);
    board[board.length - 2] = Arrays.copyOf(board[1], board[1].length);

    // You don't need member variables MainLine and BishopLine
    // and you can remove them if you want.
}

现在两行都指向不同的数组。当你打电话给movePiece(7, 0, 6, 0)你应该看到

ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK, 
PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, 
null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, 
PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, 
ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK, 



ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK, 
PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, 
null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, 
ROOK, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, 
null, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK, 
另一答案

问题出在resetBoard()函数中。在这里,您对两个玩家的棋子使用相同的对象参考。因此,当java传递值时,board [7] [0]和board [0] [0]都指向同一个对象,当一个改变时,另一个是。

为简单起见,您可以尝试下面的内容

或者在件类中创建一个复制构造函数并从resetBoard方法调用

或者覆盖件类中的clone()方法来执行对象的深层复制,这样两个引用就不会指向公共对象。

或使用Arrays.copyOf(arrayToCopy,length)创建新副本。

 private void resetBoard() {
    board = new Pieces[8][8];
    board[0] = new Pieces[]{Pieces.ROOK, Pieces.KNIGHT, Pieces.BISHOP, Pieces.QUEEN, Pieces.KING, Pieces.BISHOP, Pieces.KNIGHT, Pieces.ROOK};
    board[board.length - 1] = new Pieces[]{Pieces.ROOK, Pieces.KNIGHT, Pieces.BISHOP, Pieces.QUEEN, Pieces.KING, Pieces.BISHOP, Pieces.KNIGHT, Pieces.ROOK};
    board[1] = new Pieces[]{Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN};;
    board[board.length - 2] = new Pieces[]{Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN, Pieces.PAWN};;
}

以上是关于Java - 2D数组操作正在影响索引的反转的主要内容,如果未能解决你的问题,请参考以下文章

IndexError:数组反转中列表索引超出范围

迭代通过2d数组查看邻居,除了边界

IOC 控制反转Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 创建 事件监听器 对应的 动态代理 | 动态代理的数据准备 | 创建调用处理程序 | 创建动态代理实例对象 )(代码片

NumPy:在 3D 切片中使用来自 argmin 的 2D 索引数组

基于 2D 数组的 3D numpy 切片的平均值

数组反转