1

我一直在调试我的生命游戏的实现,我的主要问题看起来像是来自我如何使用数组。

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");
}

来自 Seed 的 boolean[][] 是一个 5x5 网格,除了中间行中的 3 个水平中间单元格之外都是假的(死的)

00000
00000
0+++0
00000
00000

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

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

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

如果我初始化第三个空白数组 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");
}

...然后游戏可以正常运行 1 代,然后奇怪的垃圾又回来了。

我有 2 个问题:首先,看起来我必须使用 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);
}

另外为了记录,System.arraycopy(boolean[][], 0, boolean[][], 0, boolean.length);没有正常工作,您必须遍历每一行。

4

2 回答 2

6

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

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

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

TestClass t=new TestClass();
t.test=1;
TestClass t1=t;
t1.test=6;
System.out.println(t.test); //prints 6.

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

于 2013-09-12T22:46:12.070 回答
1

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

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

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

在没有看到您的位移代码的情况下,我敢打赌这是由更高级别的问题引起的。您的位移算法很可能在某处存在错误。

您是否使用 Eclipse 的调试器单步执行了您的代码?如果没有,请阅读本教程并尝试一些不同的种子。这将告诉您算法中发生位移错误的位置(如果有的话)。

http://www.vogella.com/articles/EclipseDebugging/article.html

于 2013-09-12T23:27:16.137 回答