生命处理游戏
Game of Life Processing
import processing.core.PApplet;
public class gl extends PApplet {
static int neighborCount;
static int screenRows;
int tNC; // Temporary Neighbor Count
int newState;
int columns = 960;
int rows = 477;
int[][] cells = new int[columns][rows];
int[][] newGen = new int[columns][rows];
public static void main(String[] args) {
PApplet.main("gl");
}
public void settings() {
size(1920, 955);
}
public void setup() {
// Set background white and all of cells[][] to 0 or 1
screenRows = 0;
background(255);
for (int j = 0; j < (rows / 2); j++) {
for (int i = 0; i < (columns / 2); i++) {
cells[i][j] = (int) random(0, 2);
}
}
}
public void draw() {
// If program has finished generating this frame, reset everything and set cells[][] equal to newGen[][]
if (screenRows > (height / 2)) {
screenRows = 0;
System.out.println("End of generation reached");
background(255);
cells = newGen.clone();
for (int i = 0; i < columns; i++) {
for (int j = 0; j < rows; j++) {
newGen[i][j] = 0;
}
}
}
// Go through every element in cells[][], determine it's value, and display it
for (int x = 1; x < (width / 2) - 1; x++) {
for (int y = 1; y < (height / 2) - 1; y++) {
printCell(x, y);
}
}
screenRows++;
}
public void printCell(int x, int y) {
setCellState(x, y);
if (newGen[x][y] == 0) {
stroke(255);
fill(255);
} else if (newGen[x][y] == 1) {
stroke(0);
fill(0);
}
System.out.println(x + ", " + y);
rect(x, y, 2, 2);
}
public void setCellState(int x, int y) {
tNC = getNeighborCount(x, y);
neighborCount = 0;
System.out.println(tNC);
if (tNC < 2) { // If less than 2 neighbors, cell dead
newGen[x][y] = 0;
} else if (tNC > 3) { // If more than 3 neighbors, cell dead
newGen[x][y] = 0;
} else if ((tNC == 2 || tNC == 3) && cells[x][y] == 1) { // If 2 or 3 neighbors and cell is alive, do nothing (unnecessary statement but makes visualizing easier)
} else if (tNC == 3 && cells[x][y] == 0) { // If 3 neighbors and cell is dead, cell is alive
newGen[x][y] = 1;
} else if (tNC == 2 && cells[x][y] == 0) { // If 2 neighbors and cel is dead, do nothing (also unnecessary)
} else {
System.out.println("Error in setCellState(int, int);"); // In event of none of the conditions being met
}
tNC = 0; // Reset variable (probably unnecessary but might as well)
}
public int getNeighborCount(int x, int y) {
// Go through each cell adjacent or diagonal to the cell and add it's value (0 or 1) to neighborCount
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
neighborCount += cells[i + x][j + y];
}
}
// Subtract the value of the cell being evaluated from neighborCount as that is not a factor in the sum of the neighbors
neighborCount -= cells[x][y];
return neighborCount;
}
}
我现在只是追求功能而不是速度。
我正在尝试使用 Eclipse 中的 Processing 编写 Conway 的生命游戏。上面的代码在多个方面是功能失调的:
window 中显示的世代比我想要的要小得多。它只占 window 的一小部分,尽管我努力通过使每个单元格为 2x2 像素和行数和列数的一半来平衡这一点 window 的高度和宽度。
另外,第一代显示几秒后window中似乎没有更新
我注意到变量 tNC 通常等于 0,而它应该等于 0 到 7 之间的任何数字。
您遇到了三个主要问题。
问题 1: 你似乎在渲染单元格时生成了下一代,这可能没问题......但是你用 screenRows
逻辑(draw()
函数中的 if
语句)?
如果我是你,我会将你的逻辑分为两部分:编写一个绘制你的板的函数,另一个函数 returns 基于当前板的新板。不要在绘制当前一代时尝试计算下一代,因为这只会让您头疼不已。
我也不认为你在数组之间切换的逻辑是正确的。哪个数组保存当前一代,哪个保存下一代?你确定吗?
问题 2: 您似乎在像素大小和数组坐标之间切换。例如,您在其数组索引坐标处绘制每个单元格,但您将它们绘制为 2x2
矩形。这没有多大意义,因为无论如何您都将使用下一个单元格在它上面绘制。再次,分离您的逻辑:创建一个函数,根据 window width
和 height
、数组位置和数组长度绘制单元格。
问题 3: 您的打印语句正在扼杀您的帧率。打印语句是出了名的慢。由于您正在进行的所有计算,您的帧率已经很慢了,但是当您每帧打印出 (960*477*2) 东西时,它会变得更慢。这并不是一个真正的逻辑错误,但它使您更难准确地看到您的程序在做什么。
解决方案:要解决您的问题,我建议您重构您的代码。如果我是你,我会重新开始一个新程序。那么:
第 1 步:将绘图逻辑与计算下一代的逻辑分开。创建两个函数:一个用于绘图,另一个 returns 基于当前数组的新数组。
第 2 步: 在绘图代码中,确保将数组索引和像素位置分开。也许编写另一个函数,它获取一个单元格位置并根据 window 大小和数组大小绘制一个矩形。
PS:你和this person在同一个class吗?您也在使用 Daniel Shiffman 的代码吗?
import processing.core.PApplet;
public class gl extends PApplet {
static int neighborCount;
static int screenRows;
int tNC; // Temporary Neighbor Count
int newState;
int columns = 960;
int rows = 477;
int[][] cells = new int[columns][rows];
int[][] newGen = new int[columns][rows];
public static void main(String[] args) {
PApplet.main("gl");
}
public void settings() {
size(1920, 955);
}
public void setup() {
// Set background white and all of cells[][] to 0 or 1
screenRows = 0;
background(255);
for (int j = 0; j < (rows / 2); j++) {
for (int i = 0; i < (columns / 2); i++) {
cells[i][j] = (int) random(0, 2);
}
}
}
public void draw() {
// If program has finished generating this frame, reset everything and set cells[][] equal to newGen[][]
if (screenRows > (height / 2)) {
screenRows = 0;
System.out.println("End of generation reached");
background(255);
cells = newGen.clone();
for (int i = 0; i < columns; i++) {
for (int j = 0; j < rows; j++) {
newGen[i][j] = 0;
}
}
}
// Go through every element in cells[][], determine it's value, and display it
for (int x = 1; x < (width / 2) - 1; x++) {
for (int y = 1; y < (height / 2) - 1; y++) {
printCell(x, y);
}
}
screenRows++;
}
public void printCell(int x, int y) {
setCellState(x, y);
if (newGen[x][y] == 0) {
stroke(255);
fill(255);
} else if (newGen[x][y] == 1) {
stroke(0);
fill(0);
}
System.out.println(x + ", " + y);
rect(x, y, 2, 2);
}
public void setCellState(int x, int y) {
tNC = getNeighborCount(x, y);
neighborCount = 0;
System.out.println(tNC);
if (tNC < 2) { // If less than 2 neighbors, cell dead
newGen[x][y] = 0;
} else if (tNC > 3) { // If more than 3 neighbors, cell dead
newGen[x][y] = 0;
} else if ((tNC == 2 || tNC == 3) && cells[x][y] == 1) { // If 2 or 3 neighbors and cell is alive, do nothing (unnecessary statement but makes visualizing easier)
} else if (tNC == 3 && cells[x][y] == 0) { // If 3 neighbors and cell is dead, cell is alive
newGen[x][y] = 1;
} else if (tNC == 2 && cells[x][y] == 0) { // If 2 neighbors and cel is dead, do nothing (also unnecessary)
} else {
System.out.println("Error in setCellState(int, int);"); // In event of none of the conditions being met
}
tNC = 0; // Reset variable (probably unnecessary but might as well)
}
public int getNeighborCount(int x, int y) {
// Go through each cell adjacent or diagonal to the cell and add it's value (0 or 1) to neighborCount
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
neighborCount += cells[i + x][j + y];
}
}
// Subtract the value of the cell being evaluated from neighborCount as that is not a factor in the sum of the neighbors
neighborCount -= cells[x][y];
return neighborCount;
}
}
我现在只是追求功能而不是速度。
我正在尝试使用 Eclipse 中的 Processing 编写 Conway 的生命游戏。上面的代码在多个方面是功能失调的:
window 中显示的世代比我想要的要小得多。它只占 window 的一小部分,尽管我努力通过使每个单元格为 2x2 像素和行数和列数的一半来平衡这一点 window 的高度和宽度。
另外,第一代显示几秒后window中似乎没有更新
我注意到变量 tNC 通常等于 0,而它应该等于 0 到 7 之间的任何数字。
您遇到了三个主要问题。
问题 1: 你似乎在渲染单元格时生成了下一代,这可能没问题......但是你用 screenRows
逻辑(draw()
函数中的 if
语句)?
如果我是你,我会将你的逻辑分为两部分:编写一个绘制你的板的函数,另一个函数 returns 基于当前板的新板。不要在绘制当前一代时尝试计算下一代,因为这只会让您头疼不已。
我也不认为你在数组之间切换的逻辑是正确的。哪个数组保存当前一代,哪个保存下一代?你确定吗?
问题 2: 您似乎在像素大小和数组坐标之间切换。例如,您在其数组索引坐标处绘制每个单元格,但您将它们绘制为 2x2
矩形。这没有多大意义,因为无论如何您都将使用下一个单元格在它上面绘制。再次,分离您的逻辑:创建一个函数,根据 window width
和 height
、数组位置和数组长度绘制单元格。
问题 3: 您的打印语句正在扼杀您的帧率。打印语句是出了名的慢。由于您正在进行的所有计算,您的帧率已经很慢了,但是当您每帧打印出 (960*477*2) 东西时,它会变得更慢。这并不是一个真正的逻辑错误,但它使您更难准确地看到您的程序在做什么。
解决方案:要解决您的问题,我建议您重构您的代码。如果我是你,我会重新开始一个新程序。那么:
第 1 步:将绘图逻辑与计算下一代的逻辑分开。创建两个函数:一个用于绘图,另一个 returns 基于当前数组的新数组。
第 2 步: 在绘图代码中,确保将数组索引和像素位置分开。也许编写另一个函数,它获取一个单元格位置并根据 window 大小和数组大小绘制一个矩形。
PS:你和this person在同一个class吗?您也在使用 Daniel Shiffman 的代码吗?