Игра жизни - края не меняются - PullRequest
0 голосов
/ 13 марта 2019

Я видел «Игру жизни» Конвея и хотел создать свою собственную. Однако клетки по краям почему-то не следуют правилам и просто остаются живыми (или мертвыми) все время. Кто-нибудь знает, где я допустил ошибку? Это мой код: (Я только загрузил класс, в котором применил правила. Если для решения проблемы нужны другие классы, я также могу загрузить их)

import java.util.Arrays;
/**
 * The class Grid does the initialization of the game of life and the application of the rules. 
 * It is a 2D array of the type Cell. It saves the cells and uses a copy of it to apply the rules.
 *
 */
public class Grid
{
    public int col;
    public int row;
    public int x,y;
    public Cell [][] array; //2D array of the type Cell
    public Cell [][] arraycopy; 

    /**
     * This constructor is to create the initial generation of cells and set the state of random 20% to true (=alive).
     * @param col   the number of columns 
     * @param row   the number of rows
     *
     */
    public Grid(int col, int row)
    {
        this.col = col;
        this.row = row;
        this.array =  new Cell [col][row];
        //Loops through every spot in the 2D array 
        for (int x = 0; x < col; x++)
        {
            for (int y=0; y < row; y++)
            {
                //set randomly 20% of the cells' state to "true"
                if (Math.random() <= 0.2) 
                {
                    Cell cell = new Cell (true);
                    this.array[x][y]= cell;
                }
                else 
                {
                    Cell cell = new Cell (false);
                    this.array[x][y]= cell;
                }
            }
        }
    }

    /**
     * This method will count the alive cells in a 3*3 neighboorhood and apply the rules of life. 
     * This method uses arraycopy.
     *
     */
    public void lifeSteps()
    {        
        //Works with a copy of the array and the cells
        this.arraycopy =  new Cell [col][row];
        for (int x = 0; x < col; x++)
        {
            for (int y=0; y < row; y++) 
            {
                this.arraycopy [x][y] = new Cell(this.array[x][y].getState());
            }
        }
        //Looping through the cells, but the cells at the edge are skipped
        for (int x = 1; x < col-1; x++) 
        {
            for (int y= 1; y < row-1; y++)
            {
                //Looping through all the neighbors
                int numNeighborsAlive = 0;
                for (int i = x-1; i <= x+1; i++) 
                {
                    for (int j = y-1; j <= y+1; j++) 
                    {
                        //In a 3x3 neighborhood the middle cell needs to be skipped
                        if ((x != i) && (y != j))
                        {
                            //Only the cells that are alive (true) are added
                            if (arraycopy [i][j].getState() == true) 
                            {
                                numNeighborsAlive += 1;
                            }
                        }
                    }
                }
                //Apply the rules of life
                if ((array [x][y].getState()) && (numNeighborsAlive < 2 || numNeighborsAlive >3))  //Loneliness and Overpopulation
                {
                    array[x][y].setState(false); 
                } 
                else if ((array [x][y].getState() == false) && (numNeighborsAlive ==3)) //Birth
                {
                    array[x][y].setState(true); 
                } 
                else 
                { //stasis
                }
            }
        }
    }

    /**
     * This method will return the statement for the array.
     * @return  the 2D array of the type Cell
     */
    public Cell[][] returnGrid ()
    {
        return this.array;
    }

    /**
     * This method will test if everything is working well by printing zeros and ones. 
     *
     */
    public void printTest()
    { 
        System.out.println("\t"); // a new line
        for (int x = 0; x < col; x++)
        {
            for (int y=0; y < row; y++)
            {
                // assigns 1 if the cell is alive and 0 if it is dead
                if (array[x][y].getState() == true)
                {
                    System.out.print("1");
                }
                else 
                {
                    System.out.print("0");
                }
            }
            System.out.println(""); // will be displayed as colums and rows
        }
        System.out.println("\t"); // a new line
    }
}

1 Ответ

0 голосов
/ 13 марта 2019

Границы не обрабатываются, поэтому всегда есть 8 соседей.

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

Для этого я использую вектор смещения с дельтой x и дельтой y в -1, 0, 1.

private static final int[][] MIDDLE_NEIGHBORS = 
{
    {-1, -1}, {-1, 0}, {-1, 1},
    {0, -1}, {0, 1},
    {1, -1}, {1, 0}, {1, 1}
};
private static final int[][] LEFT_TOP_NEIGHBORS = 
{
    {0, 1},
    {1, 0}, {1, 1}
};
...
int[][] neighborDeltaXY(int x, int y, int col, int row) {
    if (1 < x && x < col-1 && 1 < y && y < row-1) {
        return MIDDLE_NEIGHBORS;
    }
    if (x == 0 && row == 0) {
        return LEFT_TOP_NEIGHBORS;
    }
    ...
}

Или вам может быть удобнее использовать вложенные условия:

int[][] neighborDeltaXY(int x, int y, int col, int row) {
    if (x == 0) {
        if (y == 0) {
            return LEFT_TOP_NEIGHBORS;
        } else if (y == row - 1) {
            return ...;
        } else {
            return ...;
        }
    } else if (x == col - 1) {
        if (y == 0) {
            return ...;
        } else if (y == row - 1) {
            return ...;
        } else {
            return ...;
        }
    } else {
        if (y == 0) {
            return ...;
        } else if (y == row - 1) {
            return ...;
        } else {
            return MIDDLE_NEIGHBORS;
        }
    }
}

Полезно иметь метод, выполняющий фактический подсчет на доске:

int countNeighborsAlive(Cell[][] old, int x, int y, int col, int row) {
    int numNeighborsAlive = 0;
    int[][] neighbors = neighborDeltaXY(x, y, col, row);
    for (int[] neighbor : neighbors) {
        int xn = x + neighbor[0];
        int yn = y + neighbor[1];
        if (old[xn][yn].getState()) {
            ++numNeighborsAlive;
        }
    }
    return numNeighborsAlive;
}

Итак, времяцикл становится проще:

    for (int x = 0; x < col; x++) {
        for (int y= 0; y < row; y++) {
            int numNeighborsAlive = countNeighborAlive(arraycopy, x, y, col, row);
            ... numNeighborsAlive

В игре жизни можно создавать разные геометрии, имея y == 0 в строке y == - 1, так что мир обходит границы.

Также возможно взять оригинальную доску и поместить ее в большую сетку, чтобы видимые ячейки были в [1, столбец - 1), [1, рядок - 1).В этом случае невидимые границы всегда остаются равными 0. Не очень хорошо для игры в жизнь, но другие игры, основанные на сетке, настолько замурованы.

Instead            Do             Or
x += 1;            ++x;           x++
if (c == true)     if (c)
if (d == false)    if (!d)
...