2013-10-15 9 views
5

ユーザーが準備完了ボタンをクリックするまでループを実行してから、ifステートメント内でループを開始しますが、その前にprintステートメントがあります。 。ルールセットがどのように静的であるかと関係がありますか?ボタンは何に関係なく機能しますが、printステートメントがあればループに入るだけです。ステートメントが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

'readyToStart'フィールドに' volatile'を追加してください。 –

答えて

3

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

あなたがここにマルチスレッドと並行性の問題についての詳細を読むことができます

ユーザーがクリックするまでループを実行しています準備ができているボタンをクリックして、if文の中でループを開始しますが、その前にはprint文があります。

「ユーザーが準備完了ボタンをクリックすると、ループが実行されているスレッドとは異なるスレッドでイベント処理コードが実行されています」という理由があります。したがって、予期しない動作が発生する可能性があります。 readyToStartがif条件に入る前に設定されていると仮定しているためです。

追加する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スレッドとユーザースレッドが同じ値で動作していても何らかの同期がとれることがないため、マルチスレッドの問題が発生することが想定されます。

レディフラグの宣言をchangeingかどうかをチェックすることができますができます:

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

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

関連する問題