为什么是我生命中的(采用处理)的游戏世代失灵?(Why are the generations in

2019-09-28 11:10发布

import processing.core.PApplet;
import static java.lang.System.out;

public class GoL2 extends PApplet {

int rectSideLength = 25; // rectSideLength = length of each side of the rectangles drawn that represent cells
int generation = 0;
int windowWidth = 1920;
int windowHeight = 950;

int[][] currentGeneration = new int[windowWidth][windowHeight]; // currentGeneration = 2D array to gold cell values of current generation
int[][] nextGeneration = new int[windowWidth][windowHeight]; // nextGeneration = 2D array to hold cell values of next generation

int sumOfNeighbors;
int temporarySumOfNeighbors;
int counter;

public static void main(String[] args) {
    PApplet.main("GoL2");

}

public void settings() {
    size(windowWidth, windowHeight);

}

int numRectWidth = width / rectSideLength; // numRectWidth = the number of rectangles wide that will fit in the x axis of window
int numRectHeight = height / rectSideLength; // numRectHeight = the number of rectangles that will fit in the y axis of window
                                                // The previous statements are here because they need the size of the frame to
                                                // be set in order to accurately set the variables, lest they end up equal to 100

/* public void setup() { 
 *  background(255); 
 *  frameRate(1); 
 *  for (int y = 0; y < windowHeight; y++) { // For each row, 
 *      for (int x = 0; x < windowWidth; x++) { // For each element in the current row, 
 *          currentGeneration[x][y] = (int) random(0, 2); // Set element (cell) equal to either 0 or 1 (on or off) 
 *      } 
 *  } 
 * } */

public void setup() {
    background(255);
    frameRate(1);
    for (int y = 0; y < windowHeight; y++) { // For each row,
        for (int x = 0; x < windowWidth; x++) { // For each element in the current row,
            currentGeneration[x][y] = 0; // Set element (cell) equal to either 0 or 1 (on or off)
        }
    }
    currentGeneration[25][25] = 1;
    currentGeneration[25][26] = 1;
    currentGeneration[25][27] = 1;
    currentGeneration[26][27] = 1;
    currentGeneration[27][26] = 1;

}

public void draw() {
    numRectWidth = width / rectSideLength;
    numRectHeight = height / rectSideLength;

    displayCurrentGeneration();
    try {
        Thread.sleep(2);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    fill(255, 20, 147);
    textSize(30);
    text(generation, 20, 30);

    textSize(10);
    text("25,25", 625, 645);
    text("24,27", 600, 695);
    text(generation, 580, 695);
    generation++;
    generateNextGeneration();

}

public void displayCurrentGeneration() {
    background(255);
    for (int y = 0; y < 950; y++) { // For each row,
        for (int x = 0; x < 1920; x++) { // For each element in the current row,
            if (currentGeneration[x][y] == 0) { // If element equals zero, make rectangle white
                fill(255);
                stroke(0);
            } else if (currentGeneration[x][y] == 1) { // If element equals one, make rectangle black
                fill(0);
                stroke(255);
            } else {
                out.println("Inappropriate value for currentGeneration[" + x + "][" + y + "]. Value: "
                        + currentGeneration[x][y] + ", generation: " + generation);
            }
            rect(x * rectSideLength, y * rectSideLength, rectSideLength, rectSideLength); // Display rectangle (cell)
        }
    }

    // out.println("Generation " + generation);

}

public void generateNextGeneration() {
    out.println("Generating gen " + generation);
    for (int y = 1; y < numRectHeight - 1; y++) { // For each row,
        for (int x = 1; x < numRectWidth - 1; x++) { // For each element in the current row,
            sumOfNeighbors = 0;
            sumOfNeighbors = getSumOfNeighbors(x, y);
            if (sumOfNeighbors != 2 && sumOfNeighbors != 3) { // Death
                nextGeneration[x][y] = 0;
            } else if (sumOfNeighbors == 3 && currentGeneration[x][y] == 0) { // Birth
                nextGeneration[x][y] = 1;
            } else if ((sumOfNeighbors == 2 || sumOfNeighbors == 3) && currentGeneration[x][y] == 1) { // Stasis
                nextGeneration[x][y] = 1;
            }
        }
    }
    currentGeneration = nextGeneration.clone();
}

public int getSumOfNeighbors(int xAxis, int yAxis) {
    temporarySumOfNeighbors = 0;

    for (int i = -1; i < 2; i++) {
        for (int j = -1; j < 2; j++) {
            if (xAxis == 24 && yAxis == 27 && j != 0 && i != 0) {
                out.println("X" + j + ", Y" + i + ":: " + currentGeneration[xAxis + j][yAxis + i]);
            } else if (xAxis == 24 && yAxis == 27 && j == 0 && i != 0) {
                out.println("X" + ", Y" + i + ":: " + currentGeneration[xAxis + j][yAxis + i]);
            } else if (xAxis == 24 && yAxis == 27 && j != 0 && i == 0) {
                out.println("X" + j + ", Y" + ":: " + currentGeneration[xAxis + j][yAxis + i]);
            } else if (xAxis == 24 && yAxis == 27 && j == 0 && i == 0) {
                out.println("X" + ", Y" + ":: " + currentGeneration[xAxis + j][yAxis + i]);
            }
            temporarySumOfNeighbors += currentGeneration[xAxis + j][yAxis + i];
        }
    }
    temporarySumOfNeighbors -= currentGeneration[xAxis][yAxis];
    if (temporarySumOfNeighbors > 8) {
        out.println("temporarySumOfNeighbors > 8: " + temporarySumOfNeighbors);
    }
    if (xAxis == 24 && yAxis == 27) {
        out.println("Generation: " + generation + "- " + xAxis + ", " + yAxis + ": " + temporarySumOfNeighbors);
    }

    return temporarySumOfNeighbors;

 }

}

http://pastebin.com/GH51hXzJ

我尝试编写生命游戏初学者,而且我不确定如何找到我的问题的根源。 我设置了游戏,只是在安装一个简单的滑翔机开始,相信我可能已经找到了问题的影响。

我把对细胞的标记,以帮助跟踪它们。 如果你看小区(24,27),你会看到至少这个问题的一个例子。 在控制台中,我打印出小区附近整个程序的运行。 它似乎以某种方式检测所述邻域中的(24,27)将在第1代有在第2代,反之亦然(假设第一代是代0)。 我不知道该如何解释,但如果检查控制台输出,并期待在街区,你会看到它检测到的第2代的附近在1代,反之亦然。 这就是为什么当(24,27)在第1代3个邻居,它只是涉及到生活中的第3代,而在第2代,它仅有2个邻居。

请让我知道,如果你有任何问题,我很难解释我的问题。

这个问题解释请见: http://imgur.com/gallery/iRc07/new

谢谢

Answer 1:

这是你的问题的主要来源:

currentGeneration = nextGeneration.clone();

你可能会认为线将一切从复制nextGeneration进入currentGeneration ,并且它......但不是你想它的方式。

nextGeneration变量是一个二维数组。 换句话说,这是一个数组的数组。 在其他换言之, 通过所包含的值nextGeneration是数组。

当调用clone()阵列的功能,它会将旧数组的值到一个新的数组。 这里是你的问题: 你的价值观是数组。 所以,它的复制阵列 ,而不是那些第二阵列内的值。

正因为如此,无论是nextGenerationcurrentGeneration都指向同一个阵列。 所以,当你计算的下一代,现在,你改变当前一代的阵列。 这不起作用,因为寿命计算的游戏需要两个独立的阵列。

换句话说,你正在做的阵列的浅拷贝

这可能是更容易更简单的程序来解释:

public class Test {
    public static void main(String... args){

        //create an array
        int[][] array = {{1, 2, 3}, {4, 5, 6}};

        //clone the array
        int[][] arrayTwo = array.clone();

        //change the original array
        array[0][0] = 99;

        //second array has also changed!
        System.out.println(arrayTwo[0][0]);
    }
}

长话短说: 你应该几乎从不使用clone()函数。

你可以通过将阵列的深层副本解决您的问题。 有迹象表明,帮助您处理该库,或者你可以使用序列化,或者只写你自己的嵌套for循环。

但一个更简单(我认为更正确)的解决方案是: 当你不需要他们停止使用类级别的变量。

clone()问题就不是问题,除非你正在使用nextGeneration的类级变量。 这意味着,它保留调用之间的值generateNextGeneration() 而且,由于该值是指向内部的阵列currentGeneration ,这是造成所有的问题。

你已经用你的其他变量处理这个问题:注意到你如何重置sumOfNeighborstemporarySumOfNeighbors你使用它们之前。 你可以做同样的事情与nextGeneration变量。

不过,我想更进一步,摆脱所有这三个类级变量的。 将它们的声明里面使用它们的功能,这样你就不必担心他们维护函数调用之间的值。

两个音符,而我在它:

你不应该真的叫Thread.sleep()draw()函数(或任何事件功能)。 只需设置帧速率,让加工处理时间为您服务。

您正在使用一吨,你是不是绘制细胞。 你的阵列是1920x950,不过你只画那些细胞的一小部分。 这是在浪费你的细胞从来没有表现出一吨的CPU时间。 就像我在您的其他问题说,你需要更加小心像素坐标和阵列坐标之间的区分。

无论如何,这是一个很好的问题。 我觉得你越来越近。 你只需要摆脱那些多余的细胞,你会在相当良好。 祝好运。

PS:我要一个加处理标记你的问题。 如果你对未来有任何问题,它可能是一个好主意,以确保包括此标记。 否则,我不会看到它。 :p



文章来源: Why are the generations in my Game of Life (using Processing) out of order?