Java中的Game of Life程序

时间:2016-09-09 07:54:37

标签: java conways-game-of-life

我一直试图以一种相当简单(但可能是错误的)方式制作一个生命游戏计划。从技术上讲,它似乎有效,但是当我尝试运行一些测试用例时,结果不符合在线示例。

这是主要课程:

  package gameOfLife;import java.applet.*;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import gameOfLife.Cell.State;

public class CreateGame extends Applet implements Runnable, MouseListener, KeyListener {


private enum GameState {
    SETTING, START
}

private GameState state = GameState.SETTING;
private Image image;
private Graphics second;
private Cell[][] cells = new Cell[200][120];
private int indexI = 1;
private int indexJ = 1;

@Override
public void init() {
    setSize(1000, 600);
    setFocusable(true);
    Frame frame = (Frame) this.getParent().getParent();
    frame.setResizable(false);
    frame.setTitle("Game of Life - Settings");

    for (int i = 0; i < cells.length; i++) {
        for (int j = 0; j < cells[0].length; j++) {
            cells[i][j] = new Cell(i * 5, j * 5);
        }
    }
    addMouseListener(this);
    addKeyListener(this);
    super.init();
}

@Override
public void start() {
    Thread thread = new Thread(this);
    thread.start();
    super.start();
}

@Override
public void run() {
    while (true) {
        if (state == GameState.START) {
            for(int i=1; i<cells.length-1; i++){
                for(int j=1; j<cells[0].length-1; j++){
                    update(i, j);
                }
            }
        }
        repaint();
        try {
            Thread.sleep(125);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public void update(int i, int j) { //updating the cells into ALIVE/DEAD state
    int[] neighbors = new int[8];
    int sum = 0;
    for (int index = 0; index < 8; index++)
        neighbors[index] = 0;
    if (cells[i - 1][j - 1].state == State.ALIVE)
        neighbors[0] = 1;
    if (cells[i][j - 1].state == State.ALIVE)
        neighbors[1] = 1;
    if (cells[i + 1][j - 1].state == State.ALIVE)
        neighbors[2] = 1;
    if (cells[i - 1][j].state == State.ALIVE)
        neighbors[3] = 1;
    if (cells[i + 1][j].state == State.ALIVE)
        neighbors[4] = 1;
    if (cells[i - 1][j + 1].state == State.ALIVE)
        neighbors[5] = 1;
    if (cells[i][j + 1].state == State.ALIVE)
        neighbors[6] = 1;
    if (cells[i + 1][j + 1].state == State.ALIVE)
        neighbors[7] = 1;
    for (int index = 0; index < 8; index++)
        sum += neighbors[index];
    if ((sum < 2 || sum > 3) && cells[i][j].state == State.ALIVE)
        cells[i][j].state = State.DEAD;
    else {
        if (sum == 3 && cells[i][j].state == State.DEAD)
            cells[i][j].state = State.ALIVE;
    }
}

@Override
public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    Rectangle r;
    for (int i = 0; i < cells.length; i++) {
        for (int j = 0; j < cells[0].length; j++) {
            if (cells[i][j].state == State.ALIVE) {
                r = cells[i][j].getCell();
                g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(), (int) r.getHeight());
            }
        }
    }
    super.paint(g);
}

@Override
public void update(Graphics g) {
    if (image == null) {
        image = createImage(this.getWidth(), this.getHeight());
        second = image.getGraphics();
    }

    second.setColor(getBackground());
    second.fillRect(0, 0, getWidth(), getHeight());
    second.setColor(getForeground());
    paint(second);

    g.drawImage(image, 0, 0, this);
}

@Override
public void mousePressed(MouseEvent e) {
    if (state == GameState.SETTING) {
        int x = e.getX() - e.getX() % 5;
        int y = e.getY() - e.getY() % 5;

        cells[x / 5][y / 5].born();
    }
}

@Override
public void mouseEntered(MouseEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void mouseExited(MouseEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void mouseClicked(MouseEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void mouseReleased(MouseEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_SPACE) {
        if(state == GameState.START)
            state = GameState.SETTING;
        else 
            state = GameState.START;
    }

}

@Override
public void keyReleased(KeyEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void keyTyped(KeyEvent arg0) {
    // TODO Auto-generated method stub

}

}

我制作了一个程序,通过按空格键你可以从SETTING(点击屏幕创建暂停游戏的单元格)和START来改变游戏状态,这使游戏独立运行。 Cell是我创建的类,它包含Rectangle和state:

package gameOfLife;

import java.awt.Rectangle;

public class Cell {

final int Measure = 5;
public static enum State{
    DEAD, ALIVE
}

private Rectangle cell;
private int x, y;

public State state;

public void born(){
    state = State.ALIVE;
}

public Cell(int x, int y){
    state = State.DEAD;
    cell = new Rectangle(x, y, Measure, Measure);
    this.x = x;
    this.y = y;
}

public Rectangle getCell(){
    return this.cell;
}

}

如果有人可以对它进行测试并告诉我程序逻辑有什么问题,那将会很棒,因为整体工作正常,但可能会出现一些小问题,我无法用手指将其搞砸。

1 个答案:

答案 0 :(得分:2)

我已经找出了错误 - 你在迭代网格时刷新了每个单元格的状态,但正确的方法是在迭代过程中创建一个新的单元格状态网格,然后将现有的单元格状态设置为如果有意义的话,新的细胞一次性说明。

修改后的代码似乎有效:

public class CreateGame
    extends Applet
    implements Runnable, MouseListener, KeyListener
{

  private enum GameState
  {
    SETTING, START
  }

  private GameState state = GameState.SETTING;

  private Image image;

  private Graphics second;

  private Cell[][] cells = new Cell[200][120];

  private int indexI = 1;

  private int indexJ = 1;

  @Override
  public void init()
  {
    setSize(1000, 600);
    setFocusable(true);
    Frame frame = (Frame) this.getParent().getParent();
    frame.setResizable(false);
    frame.setTitle("Game of Life - Settings");

    for (int i = 0; i < cells.length; i++)
    {
      for (int j = 0; j < cells[0].length; j++)
      {
        cells[i][j] = new Cell(i * 5, j * 5);
      }
    }
    addMouseListener(this);
    addKeyListener(this);
    super.init();
  }

  @Override
  public void start()
  {
    Thread thread = new Thread(this);
    thread.start();
    super.start();
  }

  @Override
  public void run()
  {
    while (true)
    {
      if (state == GameState.START)
      {
        Cell[][] newCells = new Cell[200][120];

        for (int i = 0; i < newCells.length; i++)
        {
          for (int j = 0; j < newCells[0].length; j++)
          {
            newCells[i][j] = new Cell(i * 5, j * 5);
          }
        }

        for (int i = 1; i < cells.length - 1; i++)
        {
          for (int j = 1; j < cells[0].length - 1; j++)
          {
            update(newCells, i, j);
          }
        }

        cells = newCells; // update all cell states in one go
      }
      repaint();
      try
      {
        Thread.sleep(125);
      }
      catch (InterruptedException e)
      {
        e.printStackTrace();
      }
    }
  }

  public void update(Cell[][] newCells, int i, int j)
  { // updating the cells into ALIVE/DEAD state

    int[] neighbors = new int[8];
    int sum = 0;
    for (int index = 0; index < 8; index++)
      neighbors[index] = 0;
    if (cells[i - 1][j - 1].state == State.ALIVE)
      neighbors[0] = 1;
    if (cells[i][j - 1].state == State.ALIVE)
      neighbors[1] = 1;
    if (cells[i + 1][j - 1].state == State.ALIVE)
      neighbors[2] = 1;
    if (cells[i - 1][j].state == State.ALIVE)
      neighbors[3] = 1;
    if (cells[i + 1][j].state == State.ALIVE)
      neighbors[4] = 1;
    if (cells[i - 1][j + 1].state == State.ALIVE)
      neighbors[5] = 1;
    if (cells[i][j + 1].state == State.ALIVE)
      neighbors[6] = 1;
    if (cells[i + 1][j + 1].state == State.ALIVE)
      neighbors[7] = 1;
    for (int index = 0; index < 8; index++)
      sum += neighbors[index];

    if (cells[i][j].state == State.ALIVE)
    {
      if ((sum < 2 || sum > 3))
      {
        newCells[i][j].state = State.DEAD;
      }
      else // sum == 2 or 3
      {
        newCells[i][j].state = State.ALIVE;
      }
    }
    else if (cells[i][j].state == State.DEAD)
    {
      if (sum == 3)
      {
        newCells[i][j].state = State.ALIVE;
      }
    }  
  }

  @Override
  public void paint(Graphics g)
  {
    Graphics2D g2d = (Graphics2D) g;
    Rectangle r;
    for (int i = 0; i < cells.length; i++)
    {
      for (int j = 0; j < cells[0].length; j++)
      {
        if (cells[i][j].state == State.ALIVE)
        {
          r = cells[i][j].getCell();
          g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(), (int) r.getHeight());
        }
      }
    }
    super.paint(g);
  }

  @Override
  public void update(Graphics g)
  {
    if (image == null)
    {
      image = createImage(this.getWidth(), this.getHeight());
      second = image.getGraphics();
    }

    second.setColor(getBackground());
    second.fillRect(0, 0, getWidth(), getHeight());
    second.setColor(getForeground());
    paint(second);

    g.drawImage(image, 0, 0, this);
  }

  @Override
  public void mousePressed(MouseEvent e)
  {
    if (state == GameState.SETTING)
    {
      int x = e.getX() - e.getX() % 5;
      int y = e.getY() - e.getY() % 5;

      cells[x / 5][y / 5].born();
    }
  }

  @Override
  public void mouseEntered(MouseEvent e)
  {
    // TODO Auto-generated method stub

  }

  @Override
  public void mouseExited(MouseEvent e)
  {
    // TODO Auto-generated method stub

  }

  @Override
  public void mouseClicked(MouseEvent e)
  {
    // TODO Auto-generated method stub

  }

  @Override
  public void mouseReleased(MouseEvent e)
  {
    // TODO Auto-generated method stub

  }

  @Override
  public void keyPressed(KeyEvent e)
  {
    if (e.getKeyCode() == KeyEvent.VK_SPACE)
    {
      if (state == GameState.START)
        state = GameState.SETTING;
      else
        state = GameState.START;
    }

  }

  @Override
  public void keyReleased(KeyEvent arg0)
  {
    // TODO Auto-generated method stub

  }

  @Override
  public void keyTyped(KeyEvent arg0)
  {
    // TODO Auto-generated method stub

  }

}