Игра жизни

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

Pastebin

Сейчас я просто предпочитаю функциональность скорости.

Я пытаюсь закодировать игру Conway's Game of Life, используя Processing в Eclipse. Приведенный выше код не работает по нескольким причинам:

Отображаемое поколение появляется в окне намного меньше, чем я хочу. Он занимает лишь часть окна, несмотря на мои попытки уравновесить это, сделав каждую ячейку размером 2x2 пикселя и вдвое меньше строк и столбцов, чем окно в высоту и ширину.

Кроме того, поколение не обновляется в окне после отображения первого поколения через несколько секунд.

Я заметил, что переменная tNC часто равна 0, когда она должна быть равна любому числу от 0 до 7.


person sirmax224    schedule 12.07.2016    source источник


Ответы (1)


У вас есть три основные проблемы.

Проблема 1: кажется, что вы генерируете следующее поколение при рендеринге ячеек, что может быть нормально... но тогда что вы делаете с логикой screenRows (оператор if в вашей функции draw())?

На вашем месте я бы разделил вашу логику на две части: напишите одну функцию, которая рисует вашу доску, и другую функцию, которая возвращает новую доску на основе текущей. Перестаньте пытаться вычислить следующее поколение, пока вы рисуете текущее поколение, так как это доставит вам массу головной боли.

Я также не думаю, что ваша логика переключения между массивами верна. Какой массив содержит текущее поколение, а какой следующее поколение? Уверены ли вы?

Проблема 2. Похоже, вы переключаетесь между размерами пикселей и координатами массива. Например, вы рисуете каждую ячейку в ее индексной координате массива, но вы рисуете их как 2x2 прямоугольника. Это не имеет большого смысла, так как вы все равно будете рисовать поверх него следующей ячейкой. Опять же, разделите свою логику: создайте функцию, которая рисует ячейку на основе окна width и height, позиции массива и длины массива.

Проблема 3. Ваши операторы печати убивают частоту кадров. Операторы печати общеизвестно медленны. Ваша частота кадров уже довольно низкая из-за всех вычислений, которые вы делаете, но она становится еще медленнее, когда вы печатаете (960 * 477 * 2) вещей в каждом кадре. На самом деле это не логическая ошибка, но из-за нее становится труднее увидеть, что именно делает ваша программа.

Решение. Чтобы решить ваши проблемы, я бы рекомендовал немного реорганизовать ваш код. На вашем месте я бы начал с новой программы. Затем:

Шаг 1. Отделите логику рисования от логики расчета следующего поколения. Создайте две функции: одну для рисования и другую, которая возвращает новый массив на основе текущего.

Шаг 2. Убедитесь, что в коде отрисовки вы разделяете индексы массива и позиции пикселей. Может быть, написать другую функцию, которая принимает позицию ячейки и рисует прямоугольник в зависимости от размера окна и размера массива.

PS: вы учитесь в одном классе с этим человеком? Вы тоже используете код Дэниела Шиффмана?

person Kevin Workman    schedule 13.07.2016
comment
Я попробовал ваши предложения и начал заново, и он, безусловно, стал аккуратнее, компактнее и читабельнее, но все еще не работает. Я продолжу попытки еще некоторое время, прежде чем, возможно, вернусь сюда за дальнейшими советами. Я не из того класса с этим человеком, однако я прочитал главу из книги Дэниела Шиффмана для руководства (но я думаю, что большая часть моего кода оригинальна, или, по крайней мере, я придумал ее индивидуально). - person sirmax224; 13.07.2016
comment
Если вы снова застряли, я бы предложил сделать новый пост с вашим новым кодом. Буду рад продолжать попытки помочь. О, и я не обвинял вас в краже кода или что-то в этом роде, я просто подумал, что это интересное совпадение! - person Kevin Workman; 14.07.2016
comment
Я считаю, что добился прогресса, но моя Игра Жизни не совсем функциональна. Похоже, он как-то неправильно считает окрестности, или неправильно интерпретирует сумму, или что-то в этом роде. Не могли бы вы помочь? Спасибо stackoverflow.com/questions/38382356/ - person sirmax224; 15.07.2016