【问题标题】:Conway's Game of life overpopulation?康威的生命过剩游戏?
【发布时间】:2013-02-08 17:36:17
【问题描述】:

我正在开发康威的生命克隆游戏,因为这是一种很好的做法,但我遇到了问题。我看到有像素删除和重生,但所有像素只是散布在屏幕的最末端,然后其他像素正在重生,但那时它只是空闲。

以下是一些截图:

我将向您展示我的一些代码以实现此逻辑。全部在change方法中处理:

package main;

import java.awt.Color;
import java.awt.Graphics;

public class Functions {

  public static int pixelsize=6,gridwidth=800/6,gridheight=600/6;
  static int[][] pixels = new int[gridwidth][gridheight];
  static boolean first = true;

  public static void change(){

    for(int i = 0; i < gridwidth; i++){
      for(int j = 0; j < gridheight; j++){
        int neighbors = 0;
        //check each cell

        try{

          if(pixels[i+1][j] == 1){neighbors++;}
          if(pixels[i-1][j] == 1){neighbors++;}
          if(pixels[i+1][j-1] == 1){neighbors++;}
          if(pixels[i][j+1] == 1){neighbors++;}
          if(pixels[i][j-1] == 1){neighbors++;}
          if(pixels[i+1][j+1] == 1){neighbors++;}
          if(pixels[i-1][j-1] == 1){neighbors++;}
          if(pixels[i-1][j+1] == 1){neighbors++;}

        }catch(ArrayIndexOutOfBoundsException e){

        }

        if(neighbors == 3 || neighbors == 2 ){
          pixels[i][j] = 1;
        }else if(neighbors < 2 || neighbors >= 4){
          pixels[i][j] = 0;
        }
      }
    }
  }

  public static void render(Graphics g){

    for(int i = 0; i < gridwidth;i++){
      for(int j = 0; j < gridheight; j++){
        if(pixels[i][j] == 1){

          g.setColor(Color.red);
          g.fillRect(i*6, j*6, 6, 6);
        }
      }
    }
  }
}


感谢您的所有帮助。遗憾的是,它仍然无法正常工作。
现在它正在做同样的事情,但像这样形成钻石:

【问题讨论】:

  • 为什么忽略AIOOBE?考虑在上面的检查中使用嵌套的 for 循环,但忽略 i == 0 && j == 0 的情况,并使用 Math.min(...) 和 Math.max(...) 处理边缘情况,这样您就不必担心 AIOOBE。
  • catch(ArrayIndexOutOfBoundsException e) 这是一场暴行!永远不要做那样的事情。你的问题的解决方法其实在我的另一个答案here

标签: java simulation


【解决方案1】:

我在这里看到的主要问题是您在发现值的同时更新它们。

您应该在更新之前缓存整个网格(或至少是邻居计数),否则,当您更新(x, y) 处的元素时,您正在更改连续为(x+1,y)、(x+1,y+1) 的元素的邻居计数, (x,y+1) 通过计算当前迭代的结果。

例如,您可以像这样更新一个名为 cachedPixels 的单独数组:

for(int i = 0; i < gridwidth; i++){
    for(int j = 0; j < gridheight; j++){
        int neighbors = 0;
        // find the proper boundaries
        int minI = Math.max(0, i - 1);
        int maxI = Math.min(gridwidth, i + 2)
        int minJ = Math.max(0, j - 1);
        int maxJ = Math.min(gridheight, j + 2)

        for (int i2 = minI; i2 < maxI; i2++) {
           for (int j2 = minJ; j2 < maxJ; j2++) {
              if (i2 != i || j2 != j) {
                 if (pixels[i2][j2] == 1) {
                    neighbors++;
                 }
              }
           }
        }

        if (neighbors == 2 || neighbors == 3) {
           cachedPixels[i][j] = 1;
        } else {
           cachedPixels[i][j] = 0; // probably not even necessary as 0 is default value
        }
    }   
}

然后在使用arraycopy函数对整个数组集完成这个过程之后:

for (int i = 0; i < length; i++) {
    System.arraycopy(cachedPixels[i], 0, pixels[i], 0, cachedPixels[i].length);
}

简单地设置pixels = cachedPixels 会将“pixels”指向“cachedPixels”数组,因此改变一个会改变另一个,系统就会崩溃。

附:您用于 GoL 的规则与 John H. Conway 的不同。如果细胞有 3 个邻居,则细胞总是在下一个时间步存活,并且只有在这个时间步还活着的情况下,它们才能与 2 个邻居一起在下一个时间步存活,否则它们就会死亡:

cachedPixels[i][j] = 0; // Default value - death.
if (neighbors == 3) {
   cachedPixels[i][j] = 1;
} else if (thisCell == 1 && neighbors == 2) {
   cachedPixels[i][j] = 1;
}

【讨论】:

  • 是的,这就是问题及其解决方案。
  • 杰克:我添加了您建议的代码示例。如果可以,请留下,如果不行,请删除。
  • @HovercraftFullOfEels:没关系,别担心。我只是懒得在我的代码库周围找到任何实现;)
  • 非常感谢!现在唯一的问题是,当我将它启动时,它会以菱形展开,然后填满屏幕。
【解决方案2】:

对于这个动作,你的新生像素不应该被算作邻居,你的死亡像素应该被计算在内。它可以通过为新生像素和垂死像素设置另一个值来实现,例如 2 和 3。处理完该字段后,您提交它的状态,方法是用1 替换新生儿的值,用0 替换死亡的值。

【讨论】:

    猜你喜欢
    • 2013-02-21
    • 1970-01-01
    • 2010-09-07
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多