Java拷贝多维数组,随机错误

nex*_*006 1 java arrays

我一直在调试我的Game of Life的实现,我的主要问题看起来就像是我使用数组的方式.

public boolean[][] oldState;
public boolean[][] newState;
private boolean gameState = true;

public LifeBoard(Seed seed) {
    oldState = seed.getSeed();
    newState = new boolean[oldState.length][oldState[0].length];
    run();
}

public void run() {
    //debug code to run for x generations
    for (int i = 0; i < 5; i++) {
        BoardPrinter.print(oldState);
        evaluateCells();
        oldState = newState;        
    }
    BoardPrinter.print(oldState);
    System.out.println("game over");
}
Run Code Online (Sandbox Code Playgroud)

Seed的boolean [] []为5x5网格,除中间行的3个水平中间单元外全部为假(死)

00000
00000
0+++0
00000
00000
Run Code Online (Sandbox Code Playgroud)

evaluateCells()查看网格中的每个单元格,查看它周围的8个单元格,对它们进行计数,并根据邻居数量将新值写入newState.

应该发生什么:使用oldState计算newState,将newState复制到oldState,然后返回newState,再根据新的oldState写入每个单元格.

真正发生了什么:第一代正常工作,但之后结果越来越奇怪,它评估单元格是假的,我知道是真的,等等.问题似乎是我复制数组的方式.

如果我初始化第3个空白数组blankState [] [] = new boolean [5] [5]; 并且在运行循环期间说:

public void run() {
    //debug code to run for x generations
    for (int i = 0; i < 5; i++) {
        BoardPrinter.print(oldState);
        evaluateCells();
        oldState = newState;
            newState = blankState;
    }
    BoardPrinter.print(oldState);
    System.out.println("game over");
}
Run Code Online (Sandbox Code Playgroud)

...然后游戏正常工作1代,然后奇怪的垃圾返回.

我有两个问题:首先,看起来我必须使用System.arraycopy(),但除非有人告诉我有关多维数组的版本,否则我将编写一个简单的循环.

我真正的问题:为什么你必须使用这种特殊的System方法来复制数组?你为什么不能使用=运算符?

编辑:下面接受概念性答案.以下是解决实现问题的代码:

for (int n = 0; n < oldState.length; n++) {
            System.arraycopy(newState[n], 0, oldState[n], 0, oldState.length);
}
for (int t = 0; t < newState.length; t++) {
            System.arraycopy(blankState[t], 0, newState[t], 0, newState.length);
}
Run Code Online (Sandbox Code Playgroud)

另外,对于记录,System.arraycopy(boolean[][], 0, boolean[][], 0, boolean.length);无法正常工作,您必须遍历每一行.

ζ--*_*ζ-- 6

我真正的问题:为什么你必须使用这种特殊的System方法来复制数组?你为什么不能使用=运算符?

这实际上是一个重要的Java课程,所以要注意.你在关注吗?好.这对将来很重要.

现在,这适用于Java中的所有对象,因为数组是对象.如果你使用=那么你只设置参考,并遇到这里看到的各种乐趣.也就是说,如果我有一个带有getter和setter的简单类,TestClass使用public int 调用test,那么以下代码将起作用:

TestClass t=new TestClass();
t.test=1;
TestClass t1=t;
t1.test=6;
System.out.println(t.test); //prints 6.
Run Code Online (Sandbox Code Playgroud)

现在,为什么?因为引用tt1指向堆上的同一个对象.而这对于数组以及.要获取副本,您需要执行特定于对象的任务.有些让你clone()直接调用(Cloneable接口),有些让你把另一个实例传递给构造函数来获取一个新实例(比如ArrayList构造函数),还有一些使用实用程序方法,比如这里的数组.