用java计算康威人生游戏中的下一帧

用java计算康威人生游戏中的下一帧,java,conways-game-of-life,Java,Conways Game Of Life,试图创造一个康威的生活游戏,但显然形状不是必须的。也许有人能帮我找到这个问题 例如滑翔机: - X - - - - - - X X - - - X X - - - - - - - - - 变成这样 - - X X - - - X - - - - X X X - - - - X X X - - 但应该是这样的: - - X - - - - - - X - - - X X X - - - - - - - - 我的代码是这样的 public Frame(int x, int y)

试图创造一个康威的生活游戏,但显然形状不是必须的。也许有人能帮我找到这个问题

例如滑翔机:

- X - - - - 
- - X X - - 
- X X - - -
- - - - - - 
变成这样

- - X X - - 
- X - - - - 
X X X - - - 
- X X X - - 
但应该是这样的:

- - X - - -
- - - X - -
- X X X - -
- - - - - -
我的代码是这样的

public Frame(int x, int y) {

     setWidth(x);
     setHeight(y);

     if (x<1)
         frame = null;
      else if (y<1)
         frame = null;
      else {

       frame = new String [x][y];

         for (int i=0; i<frame.length; i++) {
            for (int j=0; j<frame[i].length; j++) {

               frame [i][j] = DEAD;
            }
         }
      } // else
   } // construktor


 public Integer getNeighbourCount(int x, int y) {

    Frame cell = new Frame(getHeight(), getWidth());
    int counter = 0;

    if(frame[x][y].equals(ALIVE))
    {
        counter = counter - 1;
    }
    for(int i=x-1; i<=x+1;i++){

        if(i<frame.length && i>0){

            for(int j=y-1; j<=y+1;j++){

                if(j<frame[i].length && j>0){

                    if (frame[i][j]==ALIVE) {
                        counter++;

                    }

                }
        }
        }
    }

    return counter;

}



public Frame nextFrame() {

    // Returns next frame


    Frame cell = new Frame(getWidth(), getHeight());
    //cell.frame = new String[getWidth()][getHeight()];

    for(int i = 0; i < frame.length; i++){
        for(int j =0; j <frame[i].length;j++){

            int n = getNeighbourCount(i,j);

                if(cell.frame[i][j]==null) {

                    cell.frame[i][j] = DEAD;
                }
               if (isAlive(i, j) && n < 2 || n > 3) {
                   cell.frame[i][j] = DEAD;
               }
               if (isAlive(i, j) && n == 3 || n == 2){
                   cell.frame[i][j] = ALIVE;
               }
               if(!isAlive(i, j) && n == 3) {          
                   cell.frame[i][j] = ALIVE;
               }
               if(isAlive(i, j) && n > 3){

                   cell.frame[i][j] = DEAD;
               }

               frame[i][j] = cell.frame[i][j];
        }

        }

    cell.toString();
    return cell;
}

    `
公共帧(int x,int y){
设定宽度(x);
设置高度(y);

如果(x,我认为问题在于在循环中迭代时复制了新值。这意味着邻居使用的是下一个勾号的值,而不是当前的值

您可以通过等待计算新帧中的所有新值来解决此问题:
cell.frame
,然后再次迭代该帧,并从
cell.frame
复制到
frame


另一种选择(在我看来更好)是在构造过程中避免克隆帧。然后您可以更改
nextFrame
方法来创建
frame
的克隆,并使用克隆在
frame
中设置新值。您在网格中迭代时正在更改死帧和活帧。您需要存储应死或活,然后表演


将坐标存储在两个ArrayList(死、活)中。第一个和第二个位置是x轴和y轴,并根据它们是否应该变为活坐标来更改这些坐标。

这里有一个可行的解决方案-对每个单元格使用
枚举
,并正确处理i/j和x/y内容(我认为)。它肯定会生成正确的第一次迭代:

static class GameOfLife {

    final int w;
    final int h;
    State[][] frame;

    enum State {

        Dead, Alive;
    }

    public GameOfLife(int w, int h) {
        this.w = w;
        this.h = h;
        frame = new State[h][w];
    }

    public void alive(int x, int y) {
        frame[y][x] = State.Alive;
    }

    public void tick() {
        frame = nextGeneration();
    }

    private int surroundingPopulation(int x, int y) {
        int pop = 0;
        for (int i = y - 1; i <= y + 1; i++) {
            for (int j = x - 1; j <= x + 1; j++) {
                // On frame - vertically.
                if ((i >= 0 && i < h)
                        // On frame horizontally.
                        && (j >= 0 && j < w)
                        // Alive
                        && (frame[i][j] == State.Alive)
                        // Not the center.
                        && (i != y || j != x)) {
                    pop += 1;
                }
            }

        }
        return pop;
    }

    private State[][] nextGeneration() {
        State[][] next = new State[h][w];
        for (int y = 0; y < h; y++) {
            for (int x = 0; x < w; x++) {
                int pop = surroundingPopulation(x, y);
                // Any live cell
                if (frame[y][x] == State.Alive) {
                    if (pop < 2) {
                        // ... with fewer than two live neighbours dies, as if caused by under-population.
                        next[y][x] = State.Dead;
                    } else if (pop > 3) {
                        // ... with more than three live neighbours dies, as if by overcrowding.
                        next[y][x] = State.Dead;
                    } else {
                        // ... with two or three live neighbours lives on to the next generation.
                        next[y][x] = State.Alive;
                    }
                } else {
                    // Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
                    if (pop == 3) {
                        next[y][x] = State.Alive;
                    }
                }
            }
        }
        return next;
    }

    @Override
    public String toString() {
        StringBuilder s = new StringBuilder();
        for (State[] row : frame) {
            for (State c : row) {
                s.append(c == State.Alive ? "X" : " ");
            }
            s.append("\r\n");
        }
        return s.toString();
    }
}

public void test() {
    GameOfLife g = new GameOfLife(6, 6);
    g.alive(1, 0);
    g.alive(2, 1);
    g.alive(3, 1);
    g.alive(1, 2);
    g.alive(2, 2);
    System.out.println("Before:\r\n" + g);
    g.tick();
    System.out.println("After:\r\n" + g);
}
GameOfLife的静态类{
最终int w;
最终int h;
状态[][]帧;
枚举状态{
死了,活着;
}
公共生活游戏(int w,int h){
这个.w=w;
这个,h=h;
帧=新状态[h][w];
}
公共无效活动(整数x,整数y){
帧[y][x]=状态。活动;
}
公共空白勾号(){
frame=nextGeneration();
}
私人整数周边人口(整数x,整数y){
int-pop=0;
对于(int i=y-1;i=0&&j3){
//…有三个以上活着的邻居死于过度拥挤。
next[y][x]=State.Dead;
}否则{
//……有两三个活着的邻居,他们的下一代就住在一起。
next[y][x]=State.Alive;
}
}否则{
//任何有三个活邻居的死细胞都会变成活细胞,就像通过繁殖一样。
如果(pop==3){
next[y][x]=State.Alive;
}
}
}
}
下一步返回;
}
@凌驾
公共字符串toString(){
StringBuilder s=新的StringBuilder();
对于(状态[]行:帧){
对于(状态c:行){
s、 追加(c==State.Alive?“X”:“);
}
s、 追加(“\r\n”);
}
返回s.toString();
}
}
公开无效测试(){
GameOfLife g=新的GameOfLife(6,6);
g、 活的(1,0);
g、 活的(2,1);
g、 活的(3,1);
g、 活的(1,2);
g、 活的(2,2);
System.out.println(“之前:\r\n”+g);
g、 勾选();
System.out.println(“之后:\r\n”+g);
}

这是我不久前编写的一个简单测试的一个片段。正如其他人所提到的,在仍在读取的情况下,不要更改活动板上的值。相反,在读取当前电路板的同时克隆电路板并对副本进行更改

我遇到的另一个问题是迭代y,然后每次迭代x,但在访问点时引用x,y。感觉像是背对背:)

//规则:
//1)任何相邻活细胞少于两个的活细胞死亡,就好像是由于人口不足造成的。
//2)任何有两个或三个活邻居的活细胞都会延续到下一代。
//3)任何有三个以上活邻居的活细胞死亡,就好像过度拥挤一样。
//4)任何有三个活邻居的死细胞都会变成活细胞,就像通过繁殖一样。
void mutateGrid(){
//将现有网格复制到下一代网格中
布尔[][]mutatedGrid=新布尔[gridXWidth][gridYHeight];
对于(int i=0;i3){
mutatedGrid[x][y]=假;
}
else if(liveneights==3){
mutatedGrid[x][y]=真;
}
}
}
网格=网格;
}
int countliveneights(int x,int y){
整数计数=0;
对于(int j=y-1;j=gridYHeight){
继续;
}
if(网格[i][j]){
计数++;
}
}
}
计数-=网格[x][y]?1:0;//从计数中删除self
返回计数;
}
概述
// Rules:
// 1) Any live cell with fewer than two live neighbours dies, as if caused by under-population.
// 2) Any live cell with two or three live neighbours lives on to the next generation.
// 3) Any live cell with more than three live neighbours dies, as if by overcrowding.
// 4) Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
void mutateGrid() {

    // Copy existing grid into the next generation's grid
    boolean[][] mutatedGrid = new boolean[gridXWidth][gridYHeight];
    for (int i = 0; i < gridXWidth; i++) {
        System.arraycopy(grid[i], 0, mutatedGrid[i], 0, gridYHeight);
    }
    // Start mutation rules
    for (int y = 0; y < gridYHeight; y++) {
        for (int x = 0; x < gridXWidth; x++) {
            int liveNeighbours = countLiveNeighbours(x,y);
            if (liveNeighbours < 2 || liveNeighbours > 3) {
                mutatedGrid[x][y] = false;
            }
            else if (liveNeighbours == 3) {
                mutatedGrid[x][y] = true;
            }
        }
    }
    grid = mutatedGrid;
}

int countLiveNeighbours(int x, int y) {
    int count = 0;
    for (int j = y-1; j <= y+1; j++) {
        for (int i = x-1; i <= x+1; i++) {
            if (i < 0 || j < 0 || i >= gridXWidth || j >= gridYHeight){
                continue;
            }
            if (grid[i][j]) {
                count++; 
            }
        }
    }
    count -= grid[x][y]?1:0; // remove self from count
    return count;
}