最终数组上的NullPointerException错误

时间:2014-04-12 20:26:03

标签: java nullpointerexception

我长期以来一直是stackoverflow的潜伏者,并且通常总能找到一个现有的线程来回答我的任何问题,但是现在我必须自己提出一个问题,因为我还没有找到答案。< / p>

我负责用Java制作的Checkers游戏的AI用于学校作业。我设计了它,以便当AI检测到它可以进行的跳跃时,它将检查是否有任何跳跃导致双跳,如果是,则选择移动而不是随机单跳。

以下是如何做到的:

1)将电路板存放在&#34;备份&#34;变量(8x8 2d阵列的&#39;对象)并检查是否有任何跳跃

2)如果是这样,请调用方法&#34; doubleJumps&#34;经历了每次可能的跳跃

3)对于每一步,另一种方法&#34;推测跳跃&#34;被调用,它返回由给定跳转

产生的新8x8板阵列

4)然后,doubleJumps接受这个新的棋盘并通过它搜索更多的跳跃,换句话说是双跳。

但是我在备份数组中得到了一个nullpointer异常......而且我已经将它追溯到这段代码(删除了不相关的部分):

    private static int[][] doubleJumps() {
    final Piece[][] backup = BoardLayout.getLayout(); //fetches the board from the game
    for(int i=0; i<8; i++) {//iterate through board; all rows
        for (int j=0; j<8; j++) {//iterate through all columns
            if(backup[i][j] != null){
                if (backup[i][j].getCol()==colAI && PieceLogic.mustJump(i, j, false)) {//if the current piece is CPU and can jump
                    if (PieceLogic.canJump(i, j, i-2, j-2)){//if the jump is up left
                        final Piece[][] newBoard = speculateJump(i, j, i-2, j-2);//speculate the jump

此时备份[i] [j]突然变为空。我无法理解为什么要这样做,因为speculateJumps方法对数组&#39; backup&#39;没有任何引用。只有在我调用speculateJumps时才会发生这种情况,否则备份数组将保持不变。以下是speculateJumps的代码:

    private static Piece[][] speculateJump(int x1, int y1, int x2, int y2) {//this function returns a hypothetical 2d board array that results from a given jump
    Piece[][] board = BoardLayout.getLayout();
    int removeX = (x1+x2)/2;
    int removeY = (y1+y2)/2;
    board[x2][y2] = board[x1][y1];
    board[x1][y1] = null;
    board[removeX][removeY]= null;
    if (x2==0) {
        board[x2][y2].promote();
    }
    return board;
}

因为你可以看到它完全独立于备份阵列。需要注意的一点是,speculateJumps与doubleJumps在同一个类中。我完全被这个难过了。很感谢任何形式的帮助。提前谢谢

1 个答案:

答案 0 :(得分:0)

您正在操纵board内的speculateJump数组,这是BoardLayout.getLayout()返回的数组。在doubleJumps内,您还backup保持(上一个)返回值getLayout()

我的猜测是getLayout()(你没有显示代码)不创建新数组,但每次返回相同的数组。这意味着board实际上指向相同数组backupspeculateJump 修改实际主板而不是工作副本。

我认为你误解了final的含义。 final变量是一个只能分配一次的变量。虽然backupboard本身永远不会指向不同的数组,但数组本身仍然可以通过这些变量进行修改:

int[] a = new int[] { 1, 2, 3 };
final int[] b = a;
b[1] = 4;
System.out.println(a[1]); // -> 4

如果您想确保speculateJump 修改原始主板(getLayout()返回的数组),您需要“克隆”返回的数组,以确保您正在处理数据的副本。这样,您可以修改副本而不会影响原始数组。在你的情况下,它甚至更棘手,因为你有一个二维数组(一个数组的数组),所以你需要做一个“深度克隆”。