Я воссоздаю «Игру жизни» Джона Конвея. Тем не менее, мои проверки правил игры неправильно определяют окружающие жизни. Почему это? - PullRequest
0 голосов
/ 08 ноября 2018

Я экспериментировал долгое время, но я просто не вижу, где моя ошибка в проверке окружающих жизней! Ребята, пожалуйста, посмотрите на мой код и посмотрите, где моя ошибка. Все в коде полностью функционально вне проверки окружающих жизней.

P.S. Извините за испорченное форматирование. Я использую Sublime, и это лучшее, что может сделать автоформатирование.

Для тех из вас, кто незнаком, вот правила для Игры Жизни: https://bitstorm.org/gameoflife/

import java.util.*;
import java.lang.*;
import java.io.*;

class Life
{
    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        String userin = in.nextLine();
        int x = 8;
        int y = 8;      
        int [][] visualize;
        if(userin.equals("glider"))
        {
            visualize = new int [][]{
                //0 is used as a boundary, 1 represents a dead cell, 2 represents an alive cell
                {0, 0, 0, 0, 0, 0, 0, 0},
                {0, 1, 1, 1, 1, 1, 1, 0},
                {0, 1, 1, 1, 1, 1, 1, 0},
                {0, 1, 1, 1, 2, 1, 1, 0},
                {0, 1, 1, 1, 1, 2, 1, 0},
                {0, 1, 1, 2, 2, 2, 1, 0},
                {0, 1, 1, 1, 1, 1, 1, 0},
                {0, 0, 0, 0, 0, 0, 0, 0}
            };
            for (int i = 0; i <= 7; i++)
            {
                for (int j = 0; j <= 7; j++)
                {
                    if (visualize[i][j] == 2) {
                        System.out.print("*");
                    } else if (visualize[i][j] == 1)
                    {
                        System.out.print(".");
                    } else if (visualize[i][j] == 0)
                    {
                        System.out.print("_");
                    }
                }
                System.out.println();
            }
            nextGen(visualize, x, y);
        } else if(userin.equals("own"))
        {
            visualize = new int [8][8];
            for(int o = 1; o <= 6; o++) //Starting it a pos 1 means pos 0 is automaically filled with a "0", which is used as the boundary
            {
                visualize[o] = new int[x];
                for(int p = 1; p <= 6; p++) //Starting it a pos 1 means pos 0 is automaically filled with a "0", which is used as the boundary
                {
                    visualize[o][p] = in.nextInt();
                }
                System.out.println(0);
                System.out.println();
            }
            for (int i = 0; i <= 7; i++)
            {
                for (int j = 0; j <= 7; j++)
                {
                    if(visualize[i][j] == 2) {
                        System.out.print("*");
                    } else if (visualize[i][j] == 1)
                    {
                        System.out.print(".");
                    } else if (visualize[i][j] == 0)
                    {
                        System.out.print("_");
                    }
                }
                System.out.println();
            }
            nextGen(visualize, x, y);
        }
        else if(userin.equals("test"))
        {
            visualize = new int [][]{
                {0, 0, 0, 0, 0, 0, 0, 0},
                {0, 1, 1, 1, 1, 1, 1, 0},
                {0, 1, 2, 2, 1, 1, 1, 0},
                {0, 1, 2, 1, 1, 1, 1, 0},
                {0, 1, 1, 1, 1, 1, 1, 0},
                {0, 1, 1, 1, 1, 1, 1, 0},
                {0, 1, 1, 1, 1, 1, 1, 0},
                {0, 0, 0, 0, 0, 0, 0, 0}
            };
            for (int i = 0; i <= 7; i++)
            {
                for (int j = 0; j <= 7; j++)
                {
                    if (visualize[i][j] == 2) {
                        System.out.print("*");
                    } else if (visualize[i][j] == 1)
                    {
                        System.out.print(".");
                    } else if (visualize[i][j] == 0)
                    {
                        System.out.print("_");
                    }
                }
                System.out.println("_");
            }
            nextGen(visualize, x, y);
        }
    }
    static void nextGen(int visualize[][], int x, int y)
    {
        int[][] life = new int[x][y];
        int alive = 0;
        //Starts at array-point 1,1
        int startX = 1;
        int startY = 1;
        System.out.println();
        System.out.println();
        System.out.println("________");
        System.out.print("_");
        for(int repeat = startX; repeat <= 6; repeat++)
        {

            while(startY <= 6)
            {
                for(int k = startX; k <=6; k++)
                {
                    for(int l = startY; l <=6; l++)
                    {
                        //BEGIN CHECK FOR SURROUNDING LIVES
                        if(!(visualize[startX + 1][startY] == 0))
                        {
        if(visualize[startX + 1][startY] == 2) //Right 1
        {
            alive++;
        }
    }
    if(!(visualize[startX][startY + 1] == 0))
    {
        if(visualize[startX][startY + 1] == 2) //Up 1
        {
            alive++;
        }
    }
    if(!(visualize[startX + 1][startY + 1] == 0))
    {
        if(visualize[startX + 1][startY + 1] == 2) // Right 1, Up 1
        {
            alive++;
        }
    }
    if(!(visualize[startX - 1][startY] == 0))
    {
            if(visualize[startX - 1][startY] == 2) //Left 1
            {
                alive++;
            }       
        }
        if(!(visualize[startX][startY - 1] == 0))
        {
            if(visualize[startX][startY - 1] == 2) // Down 1
            {
                alive++;
            }
        }
        if(!(visualize[startX - 1][startY - 1] == 0))
        {
            if(visualize[startX - 1][startY - 1] == 2) //Left 1, Down 1
            {
                alive++;
            }
        }
        if(!(visualize[startX + 1][startY - 1] == 0))
        {
        if(visualize[startX + 1][startY - 1] == 2) //Right 1, Down 1
        {
            alive++;
        }
    }
    if(!(visualize[startX - 1][startY - 1] == 0))
    {
            if(visualize[startX - 1][startY - 1] == 2) //Left 1, Down 1
            {
                alive++;
            }
        }
        //CHECKS IF THERE ARE EXACTLY 3 LIVES AROUND AN AREA. IF NOT, IT KILLS THAT AREA
        if(alive == 3)
        {
            visualize[k][l] = 2;

        } else {
            visualize[k][l] = 1;
        }
    }
}

if (visualize[startX][startY] == 2) {
    System.out.print("*");
} else if (visualize[startX][startY] == 1)
{
    System.out.print(".");
}   
//Performs the check going down the Y-axis
startY++;
}
System.out.println("_");
System.out.print("_");
//After
startX++;
startY = 1;

}
System.out.println("_______");
}
}

1 Ответ

0 голосов
/ 09 ноября 2018

Что ж, давайте будем честными, здесь есть несколько ошибок:

У вас есть лишние и запутанные циклы

В вашем методе nextGen есть четыре вложенных цикла. Вам нужно только два, чтобы пройти через каждую ячейку в сетке. Вам не нужны внешние два, только два внутренних, так что избавьтесь от двух внешних. Также избавьтесь от переменных repeat, startX и startY, так как они вам не нужны.

Вам также нужно будет пройти через все выражения, такие как visualize[startX + 1][startY] и заменить startX на k и startY на l.

Ваша логика проверки квадрата неверна

После замены startX и startY на k и l в вашем коде дважды появляются следующие строки:

                    if (!(visualize[k - 1][l - 1] == 0)) {
                        if (visualize[k - 1][l - 1] == 2) //Left 1, Down 1
                        {
                            alive++;
                        }
                    }

Таким образом, вы подсчитываете одну из восьми соседних клеток дважды, а одну из них совсем нет.

Чтобы исправить это, замените одно из вхождений этого кода следующим:

                    if (!(visualize[k - 1][l + 1] == 0)) {
                        if (visualize[k - 1][l + 1] == 2) //Left 1, Up 1
                        {
                            alive++;
                        }
                    }

Вы изменяете текущее поколение, вычисляя следующее поколение

С Life вы не можете изменять текущее поколение мира, пытаясь понять, что такое следующее поколение. В противном случае вы могли бы пометить как мертвую клетку, которая была бы необходима, чтобы поддерживать в живых другую клетку. Вместо этого вам нужно создать второй массив и записать в нем состояние следующего поколения.

Вы создали второй массив, life, но, похоже, вы его вообще не используете. Итак, давайте использовать это. Как только вы выяснили, должна ли ячейка быть живой или мертвой, присвойте это значение life[k][l] вместо visualize[k][l].

Вы также распечатываете небольшую сетку из * и . символов, представляющих состояние следующего поколения. Для этого нужно будет использовать life вместо visualize.

Вы неправильно поняли правила жизни

Ваш код в настоящее время стремится пометить любой квадрат как живой, если у него ровно три соседа, и мертвый в противном случае. Это не так, как работает Жизнь.

Живая клетка остается живой, если у нее есть два или три соседа, в противном случае она умирает. Пустая ячейка с ровно тремя соседями становится живой.

Следующий код реализует эту логику:

            if (visualize[k][l] == 2 && (alive == 2 || alive == 3)) {
                // Live cell stays alive if 2 or 3 neighbours
                life[k][l] = 2;
            }
            else if (visualize[k][l] == 1 && alive == 3) {
                // Dead cell becomes live if 3 neighbours
                life[k][l] = 2;
            }
            else {
                // Anything else: cell either dies or stays dead.
                life[k][l] = 1;
            }

Вы забыли сбросить счетчик alive

Вы устанавливаете переменную alive в 0 в начале nextGen, но при подсчете количества живых соседей для каждой ячейки вы не сбрасываете ее в ноль. Это означает, что alive подсчитывает количество живых соседей каждой ячейки, с которой встречались до сих пор. Не пройдет много времени, как эта цифра превысит 3, и все закончится мертвым.

Вам нужно сбросить alive обратно на ноль в начале цикла l.


Я внес все эти изменения в ваш nextGen метод, и он, похоже, сработал, в нем отображалось то, что я ожидал увидеть на одном поколении от планера. Вот что я закончил (IntelliJ немного отформатировал его, поэтому он не совсем отформатирован так, как ваш код):

    static void nextGen(int visualize[][], int x, int y) {
        int[][] life = new int[x][y];
        int alive = 0;

        System.out.println();
        System.out.println();
        System.out.println("________");
        System.out.print("_");

        for (int k = 1; k <= 6; k++) {
            for (int l = 1; l <= 6; l++) {
                alive = 0;
                //BEGIN CHECK FOR SURROUNDING LIVES
                if (!(visualize[k + 1][l] == 0)) {
                    if (visualize[k + 1][l] == 2) //Right 1
                    {
                        alive++;
                    }
                }
                if (!(visualize[k][l + 1] == 0)) {
                    if (visualize[k][l + 1] == 2) //Up 1
                    {
                        alive++;
                    }
                }
                if (!(visualize[k + 1][l + 1] == 0)) {
                    if (visualize[k + 1][l + 1] == 2) // Right 1, Up 1
                    {
                        alive++;
                    }
                }
                if (!(visualize[k - 1][l] == 0)) {
                    if (visualize[k - 1][l] == 2) //Left 1
                    {
                        alive++;
                    }
                }
                if (!(visualize[k][l - 1] == 0)) {
                    if (visualize[k][l - 1] == 2) // Down 1
                    {
                        alive++;
                    }
                }
                if (!(visualize[k - 1][l - 1] == 0)) {
                    if (visualize[k - 1][l - 1] == 2) //Left 1, Down 1
                    {
                        alive++;
                    }
                }
                if (!(visualize[k + 1][l - 1] == 0)) {
                    if (visualize[k + 1][l - 1] == 2) //Right 1, Down 1
                    {
                        alive++;
                    }
                }
                if (!(visualize[k - 1][l + 1] == 0)) {
                    if (visualize[k - 1][l + 1] == 2) //Left 1, Up 1
                    {
                        alive++;
                    }
                }

                if (visualize[k][l] == 2 && (alive == 2 || alive == 3)) {
                    life[k][l] = 2;
                }
                else if (visualize[k][l] == 1 && alive == 3) {
                    life[k][l] = 2;
                }
                else {
                    life[k][l] = 1;
                }

                if (life[k][l] == 2) {
                    System.out.print("*");
                }
                else if (life[k][l] == 1) {
                    System.out.print(".");
                }
            }

            System.out.println("_");
            System.out.print("_");
        }
        System.out.println("_______");

        // Copy the 'life' array back to 'visualize', so that the
        // next generation could be calculated from it.
        for (int i = 1; i < 6; ++i)
        {
            visualize[i] = life[i];
        }
    }

Пожалуйста, не торопитесь, чтобы понять изменения и почему этот код работает.

Наконец, вы пишете такой код восемь раз:

                if (!(visualize[k + 1][l] == 0)) {
                    if (visualize[k + 1][l] == 2) //Right 1
                    {
                        alive++;
                    }
                }

Вместо записи if (!(something == 0)) ... вы можете написать if (something != 0). Однако вы можете упростить этот код еще больше: если ячейка равна 2, она автоматически также не равна 0, поэтому вы можете просто написать следующее:

                if (visualize[k + 1][l] == 2) //Right 1
                {
                    alive++;
                }

Кроме того, комментарии Left, Right Up и Down неверны. Цикл k проходит по строкам (т. Е. Это y -координата), а цикл l проходит по ячейкам в каждой строке ( x -координата). Кроме того, k + 1 вниз на одну ячейку, а не вверх на одну ячейку.

...