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