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. Вышеприведенный код не работает несколькими способами:
Отображаемое поколение выглядит намного меньше в окне, чем я хочу. Это занимает всего лишь часть окна, несмотря на мои попытки уравновесить это, сделав каждую ячейку 2х2 пикселя и вдвое меньше строк и столбцов, чем окно, высокое и широкое.
Кроме того, поколение не обновляется в окне после того, как первое поколение отображается через несколько секунд.
Я заметил, что переменная tNC часто равна 0, когда она должна быть равна любому числу от 0 до 7.
1 ответ
У вас есть три основные проблемы.
Проблема 1: Похоже, вы генерируете следующее поколение при рендеринге ячеек, что может быть хорошо... но что вы делаете с screenRows
логика (if
утверждение в вашем draw()
функция)?
На вашем месте я бы разбил вашу логику на две части: напишите одну функцию, которая рисует вашу доску, и другую функцию, которая возвращает новую доску, основанную на текущей. Перестаньте пытаться вычислить следующее поколение, пока вы рисуете текущее поколение, потому что это даст вам массу головных болей.
Я также не думаю, что ваша логика для переключения между массивами верна. Какой массив содержит текущее поколение, а какой содержит следующее поколение? Уверены ли вы?
Проблема 2: Вы, кажется, переключаетесь между размерами пикселей и координатами массива. Например, вы рисуете каждую ячейку с координатой индекса массива, но рисуете их как 2x2
прямоугольники. Это не имеет большого смысла, так как вы все равно будете рисовать поверх него со следующей ячейкой. Опять же, разделите вашу логику: создайте функцию, которая рисует ячейку на основе окна width
а также height
, позиция массива и длина массива.
Проблема 3: Ваши операторы печати убивают вашу частоту кадров. Печатные заявления печально известны медлительностью. Ваша частота кадров уже довольно медленная из-за всех вычислений, которые вы делаете, но она становится еще медленнее, когда вы печатаете (960*477*2) вещи в каждом отдельном кадре. Это на самом деле не логическая ошибка, но затрудняет точное представление о том, что делает ваша программа.
Решение: Чтобы исправить ваши проблемы, я бы порекомендовал рефакторинг вашего кода. На вашем месте я бы начал с новой программы. Затем:
Шаг 1: Отделите логику рисования от логики для расчета следующего поколения. Создайте две функции: одну для рисования, а другую, которая возвращает новый массив на основе текущего.
Шаг 2. В коде чертежа убедитесь, что вы разделяете индексы массива и позиции пикселей. Может быть, написать другую функцию, которая занимает позицию в ячейке и рисует прямоугольник на основе размера окна и размера массива.
PS: Вы в одном классе с этим человеком? Вы тоже используете код Дэниела Шиффмана?