2016-09-09 93 views
0

我一直在試圖用一個相當簡單的(也許是錯誤的)方式製作一個生命遊戲程序。從技術上講,它似乎可行,但是當我試圖運行一些測試用例時,結果並不適合在線使用示例。Java中的生活程序遊戲

這裏的主類:

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 

} 

}

我的方式製作的節目,通過按空格鍵你設置(通過點擊屏幕來創建細胞上改變了遊戲狀態,這暫停遊戲)和開始,使遊戲自行運行。 細胞是一類我創建了包含矩形和狀態:

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

}

如果任何人都可以進行測試,並告訴我有什麼錯這將是偉大的程序邏輯,因爲整體的工作,但是可能存在一些小問題,我不能把手指放在哪個螺絲上。

+6

這可能是對http://codereview.stackexchange.com/ –

+0

如果你犯了一個可重複的例子,與樣品輸入這可能是適當的位置更爲合適,預期輸出的描述,以及可能的錯誤輸出樣本。 「這裏是代碼,發現錯誤」不是人們通常在這裏迴應的。 –

+0

對不起,我真的不知道這個地方是如何工作的。我想我可以像我一樣發佈它,如果有任何需要澄清或輸出的例子,我會在評論中發佈它。 – user3917631

回答

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 

    } 

} 
+0

非常感謝您的幫助!試圖upvote你的評論,但似乎我需要更多的聲譽。還有一件事,程序似乎現在工作正常,但我試圖運行這個測試用例(應該運行在一個無限循環):https://en.wikipedia.org/wiki/Gun_(cellular_automaton)# /media/File:Game_of_life_glider_gun.svg,它不起作用,代碼邏輯有問題嗎? – user3917631

+0

沒問題,很高興我能幫上忙。可能還有一個邏輯錯誤,我沒有檢查剩下的代碼。你如何設置不起作用的測試模式,你是用代碼還是手工創建模式?詢問,因爲初始配置中的單個不同單元會導致非常不同的行爲。又如何失敗? – phil76

+0

我通過han設置了模式,現在正在進行代碼設置。我準確地設置它(做了幾次,並且檢查了一次以上)。拍攝到「太空船」後,該圖案會分離。下面是最後一張圖片的樣子:http://www.siz.co.il/my.php?i=nd5jq5jzmktu.png – user3917631