我有一个循环,直到用户点击一个就绪按钮,然后它启动if语句中的循环,但它只能在它之前有一个print语句。它与规则集是如何静态有关吗? Button无论如何都可以工作,但只有当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 class RuleSet {
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 :(得分:3)
我有一个循环,一直运行,直到用户点击一个就绪按钮,然后它在if语句中启动循环,但它只能在它之前有一个print语句。
问题背后的原因是,“当用户单击就绪按钮时,事件处理代码将在与运行循环的线程不同的线程中运行”。因此,行为可能是意外的:因为您假设在进入if条件之前正在设置 readyToStart 。
添加 System.out.println 使线程运行循环以等待io,同时 readyToStart 由另一个线程设置。
你可以通过在它的声明中添加volatile来使 readyToStart 易失性,这样两个线程都可以有一致的视图。
public class RuleSet {
public Grid grid;
public static volatile boolean readyToStart = false;
/*Rest of code goes here*/
}
答案 1 :(得分:1)
首先:请不要使用is ...()方法来改变状态。这应该是一个访问器,而不是命名约定的mutator。 (您可能希望使用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