2012-04-01 50 views
1

我正在製作康威生命遊戲圖形模型的程序,但它一旦啓動就不會讓我做任何事情;按鈕不起作用,網格不變。我究竟做錯了什麼?爲什麼我的Java遊戲生活程序不工作?

import java.awt.*; 
import javax.swing.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseEvent; 


public class gameOfLife extends JApplet{ 
    private static final long serialVersionUID = 1L; 

cellClass cell; 

public void init() { 
    Container contentWindow = getContentPane(); 
    cell = new cellClass();{{ 
    setLayout(new FlowLayout()) }}; 
    contentWindow.add(cell);  
    } 
} 

class grid extends JComponent{ 
    private static final long serialVersionUID = 2L; 

    int XSIZE = 500; 
    int YSIZE = 500; 
    private int row; 
    private int col; 
    private int size = 5; 
    private cellClass c; 
    private Dimension preferredSize = new Dimension(XSIZE, YSIZE); 

    public void paint(Graphics a) { 
    int x, y; 
     for(x=0; x<row; x++){ 
     for(y=0; y<col; y++){ 
      if(c.grid[x][y] != 0){ 
       a.drawRect(x * size, y * size, 5, 5); 
      } 
     } 
    } 
    a.drawRect(0, 0, XSIZE, YSIZE); 

} 

public grid(cellClass newGrid, int newRow, int newCol, int newSize) { 
    setMinimumSize(preferredSize); 
    setMaximumSize(preferredSize); 
    setPreferredSize(preferredSize); 
    this.row = newRow; 
    this.col = newCol; 
    this.size = newSize; 
    this.c = newGrid; 

} 
} 

class cellClass extends JPanel implements ActionListener{ 
private static final long serialVersionUID = 3L; 

static final int ROW = 100; 
static final int COL = 100; 
static final int SIZE = 5; 
static final int min = 2; 
static final int max = 3; 
static final int birth = 3; 
public int genCount = 0; 

public int[][] grid; 
private int[][] nextGrid; 

private GridBagLayout gridBag = new GridBagLayout(); 
private GridBagConstraints c = new GridBagConstraints(); 

JLabel title; 
JLabel genCounter; 
JButton oneGen; 
JButton contPlay; 
JButton stop; 
public grid board; 
public boolean paused = true; 
public boolean canChange = true; 

cellClass() { 
    grid = new int [ROW][COL]; 
    nextGrid = new int[ROW][COL]; 

    makeGrid(grid); 

    setLayout(gridBag); 

    title = new JLabel("Game of Life Applet"); 
    c.gridx = 0; 
    c.gridy = 0; 
    c.gridwidth = 2; 
    c.insets = new Insets(2,0,0,0); 
    c.anchor = GridBagConstraints.WEST; 
    add(title); 

    board = new grid(this,ROW,COL,SIZE); 
    c.gridx = 0; 
    c.gridy = 2; 
    c.gridwidth = 1; 
    gridBag.setConstraints(board, c); 
    add(board); 

    oneGen = new JButton("Move one Generation"); 
    c.gridx = 0; 
    c.gridy = 3; 
    c.gridwidth = 1; 
    gridBag.setConstraints(oneGen, c); 
    add(oneGen); 

    contPlay = new JButton("Play"); 
    c.gridx = 1; 
    c.gridy = 3; 
    c.gridwidth = 1; 
      contPlay.setVisible(true); 
    gridBag.setConstraints(contPlay, c); 
    add(contPlay); 

    stop = new JButton("Stop"); 
    c.gridx = 2; 
    c.gridy = 3; 
    c.gridwidth = 1; 
      stop.setVisible(false); 
    gridBag.setConstraints(stop, c); 
    add(stop); 

    genCounter = new JLabel("Generation: 0"); 
    c.gridx = 0; 
    c.gridy = 1; 
    c.gridwidth = 1; 
    gridBag.setConstraints(genCounter, c); 
    add(genCounter); 
} 

class ButtonListener { 
    public void addActionListener(ActionEvent e) throws InterruptedException { 
     JButton source = (JButton)e.getSource(); 

     if(source == oneGen){ 
      nextGen(); 
     } 
     if(source == contPlay){ 
      paused = false; 
      canChange = false; 
          contPlay.setVisible(false); 
          stop.setVisible(true); 
      while (paused = false) { 
       nextGen(); 
       Thread.sleep(1000); 
      } 
     } 
     if(source == stop) { 
      paused = true; 
      canChange = false; 
          stop.setVisible(false); 
          contPlay.setVisible(true); 
     } 
    } 
} 

public void mouseClicked(MouseEvent e){ 
    int xco = e.getX() - board.getX(); 
    int yco = e.getY() - board.getY(); 
    if((e.getComponent() == board) && (paused == true)){ 
     if(grid[xco/5][yco/5] == 1){ 
      grid[xco/5][yco/5] = 0; 
      board.repaint(); 
     }else if(grid[xco/5][yco/5] == 0){ 
      grid[xco/5][yco/5] = 1; 
      board.repaint(); 
     } 
    } 
} 

public void makeGrid(int[][] emptyGrid) { 
    int x, y; 
    for(x = 0; x < ROW; x++){ 
     for(y = 0; y < COL; y++){ 
      emptyGrid[x][y] = 0; 
     } 
    } 
} 

public void nextGen() { 
    getNextGen(); 
    board.repaint(); 
    genCount++; 
    genCounter.setText("Generation: " + Integer.toString(genCount));   
} 

public void getNextGen() { 
    int x, y, neighbor; 
    makeGrid(nextGrid); 
    for(x = 0; x < ROW; x++){ 
     for(y=0; y<COL; y++){ 
      neighbor = calculate(x,y); 

      if(grid[x][y] != 0){ 
       if((neighbor >= min) && (neighbor <= max)) { 
        nextGrid[x][y] = neighbor; 
       } 
      }else { 
       if(neighbor == birth){ 
        nextGrid[x][y] = birth; 
       } 
      } 
     } 
    } 
    makeGrid(grid); 
    copyGrid(nextGrid,grid); 
} 

public void copyGrid(int[][] source, int[][] newGrid) { 
    int x, y; 
    for(x=0; x<ROW; x++){ 
     for(y=0; y<COL; y++){ 
      newGrid[x][y] = source[x][y]; 
     } 
    } 
} 

private int calculate(int x, int y){ 
    int a, b, total; 

    total = (grid[x][y]); 
    for (a = -1; a<= 1; a++) { 
     for (b = -1; b <= 1; b++){ 
      if(grid[(ROW + (x + a)) % ROW][(COL + (y + b)) % COL] != 0) { 
       total++; 
      } 
     } 
    } 
    return total; 
} 

@Override 
public void actionPerformed(ActionEvent arg0) { 
    // TODO Auto-generated method stub 

    } 
}  

如果有人能告訴我它有什麼問題,那就太棒了。

+0

小應用程序也必須在[事件派發線程](http://download.oracle.com/javase/tutorial/uiswing/concurrency/initial.html)上有GUI對象。 – trashgod 2012-04-01 03:08:43

+0

另請參閱此[生命遊戲](http://stackoverflow.com/a/8200046/418556)版本。小程序是一個高級話題。代碼'JFrame'的應用程序。目前來說。 – 2012-04-01 03:33:29

回答

5

你的一個主要問題是,你嘗試在運行一個漫長的過程Swing事件線程,也被稱爲Event Dispatch Thread或EDT,這實際上會凍結您的程序。我看到發生這個問題在這裏:

class ButtonListener { 
    public void addActionListener(ActionEvent e) throws InterruptedException { 
    JButton source = (JButton) e.getSource(); 

    // ... 

     while (paused = false) { // ******* 
      nextGen(); 
      Thread.sleep(1000); // ****** 
     } 
    } 

    // ... 

} 

你同時擁有while(true)環路和Thread.sleep(...)這兩者都不應該在事件線程中調用。您可以使用Swing Timer

有關Swing事件線程的更多信息,請閱讀Concurrency in Swing。 (1),你在哪裏允許單元格初始化爲活着?如果沒有活細胞開始,所有世代都將只顯示一個空格子?您是否需要將MouseListener添加到一個或多個組件中?我認爲這將是一個好主意。

另外(2)按鈕通常在將動作偵聽器添加到它們時會更好,這在Swing button tutorial中有很好的概述。你經歷過Swing教程嗎?如果沒有,請檢查他們(找到他們here),因爲他們會幫助你很多,我想。 (3)你可能會咬掉更多的東西,因爲你一次試圖解決太多的問題。當我創建一個類似於此的GUI時,我喜歡單獨對程序的每個部分進行處理,並在將它整合到一個大程序中之前先讓它工作。舉例來說,首先在非GUI模型上工作,並通過調用模型方法的測試代碼來運行代碼。接下來,每次在GUI的每個部分工作一次,包括JButtons,然後是MouseListener,然後顯示生命遊戲,然後執行這些世代。

調試較小的測試程序然後試圖調試整個shebang相當容易,相信我。

+0

感謝您的幫助。這一定會幫助我得到它的工作。 – Areth 2012-04-01 03:36:14

+0

@Areth:不客氣。另請閱讀「另(3)」。 – 2012-04-01 03:41:11

+1

@HovercraftFullOfEels你確定'while(paused = false)'等於'while(true)'嗎?這是一個賦值而不是比較('==')。我甚至不知道這是有效的Java語法。我的IDE建議它等於'while(false)'iso while(true)' – Robin 2012-04-01 06:03:25

0

也許嘗試init()中的super.init()?

+2

此答案有任何幫助的機會?認真。 – 2012-04-01 02:17:12

+1

@RayTayek - 在發佈答案之前,你確實應該檢查一下。 – 2012-04-01 02:40:23

1

你的程序啓動了我,但有其他問題。 這將幫助您開始使用固定的問題:

變化:

cell = new cellClass(); 

要:

cell = new cellClass(){{ 
    setLayout(new FlowLayout()); 
}}; 
+0

謝謝,我把它變成了一個新的類(在一個新的項目中),並加載它。感謝您指出我應該注意的事項。 – Areth 2012-04-01 01:29:45