【问题标题】:Game of life - edges do not change生命的游戏 - 边缘不会改变
【发布时间】:2019-03-13 10:16:01
【问题描述】:

我看了康威的生命游戏,想自己制作。然而,边缘的细胞不知何故不遵守规则,只是一直活着(或死了)。有人知道我在哪里犯了错误吗? 这是我的代码:(我只上传了我应用规则的类。如果需要其他类来解决问题,我也可以上传)

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

【问题讨论】:

  • 我认为您的评论 //Looping through the cells, but the cells at the edge are skipped 可能是相关的 ;-)

标签: java arrays conways-game-of-life


【解决方案1】:

不处理边界,所以总是有8个邻居。

可以处理所有个数组位置,并确定邻居。这些可以在初始化时硬连线在单元中,或者 - 如下 - 动态确定。

为此,我使用了一个偏移向量,其中 delta x 和 delta 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, col - 1), [1, row - 1)。不可见的边界总是保持为 0。对于生活游戏来说不是很好,但其他基于网格的游戏是如此封闭。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-30
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-30
    相关资源
    最近更新 更多