2013-10-15 56 views
5

之前,如果打印進入我有一臺運行,直到用戶點擊一個現成的按鈕循環,然後它開始的if語句內的循環,但它僅適用它有前一個print語句。它是否與規則集是靜態的有關?該按鈕無論如何工作,但只有在打印語句存在時纔會進入循環。如果語句只

package gameoflife; 

public class GameOfLife { 

    public static final int HEIGHT = 16; 
    public static final int LENGTH = 16; 
    public static Grid current; 

    public static void main(String[] args) { 
     Ui gui = new Ui(); 
     int time = 0; 
     while (true) { 
      RuleSet.checkReady(); 
      //System.out.println(RuleSet.checkReady()); 
      if (RuleSet.checkReady() == true) { 
       //System.out.println("ready!"); 
       if(time == 0){ 
        current = gui.getUserSeed(); 
       } 
       while (time < 100) { 
        current.print(); 
        Grid next = new Grid(HEIGHT, LENGTH); 
        for (int i = 0; i < HEIGHT; i++) { 
         for (int j = 0; j < LENGTH; j++) { 
          next.changeState(i, j, RuleSet.determineState(current, i, j)); 
         } 
        } 
        current = next; 
        time++; 
       } 
       break; 
      } 
     } 
    } 
} 

規則類:

公共類規則集{

public Grid grid; 
public static boolean readyToStart = false; 

/*checkReady() 
* input: 
* purpose: checks ready flag 
* output: none 
*/ 
public static boolean checkReady() { 
    return readyToStart; 
} 

/*isReady() 
* input: none 
* purpose: sets ready flag to ready 
* output: none 
*/ 
public static void isReady() { 
    readyToStart = true; 
} 

/*determineState() 
* input: Grid grid, int y, int x 
* purpose: determines the state of a cell for the next 
*   generationusing the four rules below 
* output: true/false 
*/ 
public static boolean determineState(Grid grid, int y, int x) { 
    grid = grid; 
    int neighbors = grid.getNeighbors(y, x); 
    if (grid.getState(y, x)) { 
     return (ruleOne(neighbors) && ruleTwo(neighbors) 
       && ruleThree(neighbors)); 
    } else { 
     return (ruleFour(neighbors)); 
    } 
} 

/* 
* Rule 1: 
* Any live cell with fewer than two live neighbours dies, 
* as if caused by under-population. 
*/ 
private static boolean ruleOne(int neighbors) { 
    return (neighbors >= 2); 
} 

/* 
* Rule 2: 
* Any live cell with two or three live neighbours 
* lives on to the next generation. 
*/ 
private static boolean ruleTwo(int neighbors) { 
    return (neighbors == 2 || neighbors == 3); 
} 

/* 
* Rule 3: 
* Any live cell with more than three live neighbours dies, 
* as if by overcrowding 
*/ 
private static boolean ruleThree(int neighbors) { 
    return (neighbors < 4); 
} 

/* 
* Rule 4: 
* Any dead cell with exactly three live neighbours becomes a live cell, 
* as if by reproduction. 
*/ 
private static boolean ruleFour(int neighbors) { 
    return (neighbors == 3); 
} } 

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Container; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

/** 
* 
* @author peter 
*/ 
public class Ui extends JFrame { 

public static JPanel panelGrid; 
public static JPanel panelControl; 
public static JPanel panelManager; 
public static JButton[][] buttons; 
public static JButton isReady; 
public static JButton nextGen; 
public static final int HEIGHT = 16; 
public static final int LENGTH = 16; 
public Grid temp; 

public Ui() { 
    setTitle("The Game Of Life"); 
    setSize(800, 600); 
    setLocationRelativeTo(null); 
    setDefaultCloseOperation(EXIT_ON_CLOSE); 
    temp = new Grid(HEIGHT, LENGTH); 
    //Creates and sets up the contentPane Container 
    Container contentPane = getContentPane(); 
    contentPane.setLayout(new BorderLayout()); 
    contentPane.add(initButtonGrid(), BorderLayout.CENTER); 
    contentPane.add(initContButton(), BorderLayout.PAGE_END); 
    //add(contentPane); 
    setVisible(true); 
} 

/*initButtonGrid() 
* input: none 
* purpose: to return initialize the button array, and return the 
*   corresponding JPanel 
* output: JPanel panelGrid 
*/ 
private JPanel initButtonGrid() { 
    buttons = new JButton[HEIGHT][LENGTH]; 
    panelGrid = new JPanel(new GridLayout(HEIGHT, LENGTH)); 

    for (int i = 0; i < HEIGHT; i++) { 
     for (int j = 0; j < LENGTH; j++) { 
      buttons[i][j] = new JButton(); 
      buttons[i][j].setSize(80, 80); 
      buttons[i][j].setBackground(Color.white); 
      //Creates an action listener that allows user 
      //to setup seed 
      buttons[i][j].addActionListener(new ActionListener() {      
       //Loops through and checks the state of the button/array 
       //and then changes state if needed 
       public void actionPerformed(ActionEvent e) { 
        for (int i = 0; i < HEIGHT; i++) { 
         for (int j = 0; j < LENGTH; j++) { 
          if (buttons[i][j] == e.getSource() 
            && !RuleSet.checkReady()) { 
           temp.changeState(i, j, !temp.getState(i, j)); 
           if (temp.getState(i, j)) { 
            buttons[i][j].setBackground(Color.red); 
           } else { 
            buttons[i][j].setBackground(Color.white); 
           } 
           temp.print(); 
          } 
         } 
        } 
       } 
      }); 
      panelGrid.add(buttons[i][j]); 
     } 
    } 
    return panelGrid; 
} 

/*getUserSeed() 
* input: none 
* purpose: to return the seed the user made with the buttons. I was having 
*   trouble passing the current grid from main() to here in a static 
*   way. Will attempt to update at later point 
* output: Grid temp 
*/ 
public Grid getUserSeed() { 
    return temp; 
} 

/*initContButton() 
* input: none 
* purpose: to return initialize the buttons for commands, and return the 
*   corresponding JPanel 
* output: JPanel panelControl 
*/ 
private JPanel initContButton() { 
    panelControl = new JPanel(new GridLayout(1, 2)); 
    JButton ready = new JButton("Start Simulation"); 
    ready.setSize(80, 190); 
    ready.addActionListener(new ActionListener() { 

     public void actionPerformed(ActionEvent e) { 
      RuleSet.isReady(); 
      System.out.println("Ready Pressed"); 
     } 
    }); 
    panelControl = new JPanel(new GridLayout(1, 2)); 
    JButton nextGen = new JButton("Generation"); 
    nextGen.setSize(80, 190); 
    nextGen.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
     } 
    }); 
    panelControl.add(ready); 
    panelControl.add(nextGen); 
    return panelControl; 
} 
} 
+0

您從未將標誌設置爲「true」。 –

+0

我將添加gui類,但有一個按鈕具有一個操作事件將其設置爲true; –

+0

將'volatile'添加到'readyToStart'字段中。 –

回答

3

我有一個循環,直到用戶點擊運行一個準備就緒的按鈕,然後它啓動if語句中的循環,但它只起作用,它之前有一個打印語句。

問題背後的原因是,「當用戶單擊就緒按鈕時,事件處理代碼正在與您的循環運行的線程不同的線程中運行」。你在給,如果條件之前,因爲你是假設 readyToStart被設置:那麼,行爲可以是意外。

添加的System.out.println使得運行循環等待IO和在同時 readyToStart正在被其他線程設置的線程。

您可以使 readyToStart通過在它的聲明中添加volatile來揮發,以便兩個線程都可以擁有它的一致性視圖。

public class RuleSet { 

      public Grid grid; 
      public static volatile boolean readyToStart = false; 

      /*Rest of code goes here*/ 
} 
1

第一:請不要使用is ...()方法來改變狀態。這應該是一個訪問者,而不是命名約定的增變。 (您可能需要使用userIsReady()或setReady())。

我假設你遇到一個多線程的問題,因爲你有AWT線程和用戶線程具有相同價值的工作,但還沒有確保有某種同步。

您可以檢查是否量變到質變的準備標誌的聲明幫助:

public static boolean readyToStart = false; // change this to 
public volatile static boolean readyToStart = false; 

你可以閱讀更多關於多線程和併發問題在這裏:

http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html

http://docs.oracle.com/javase/tutorial/uiswing/concurrency/