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

问题描述 投票:1回答:2

我正在尝试通过运用我的知识和制作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();
    }

}
java arrays multidimensional-array chess
2个回答
1
投票

问题出在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, 

1
投票

问题出在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};;
}
© www.soinside.com 2019 - 2024. All rights reserved.