循环冻结程序时保持计算,并在计算之间暂停

时间:2013-10-23 22:30:55

标签: java

您好我有这个代码,您点击几个立方体将它们设置为死或活,根据一组规则,java将计算下一步后哪些单元格将活着/死亡。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
class GameOfLife implements ActionListener{
Scanner scanner;                                                               //to      read the text file
File file;
boolean play = false;
String filename = "birth.txt";                                                 //the file that has to be read
Cell[][] cells=new Cell[10][10];                                               //array containing all the cells
JButton nextButton;
JButton playButton;
JPanel buttonPanel;
JPanel cellPanel;
GridLayout gridLayout=new GridLayout(10,10);
JFrame frame=new JFrame();
void buildit(){
    readInput();
    frame.setSize(600,700);        
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    buttonPanel=new JPanel();
    buttonPanel.setPreferredSize(new Dimension(600,100));
    frame.add(buttonPanel, BorderLayout.PAGE_START);
    nextButton=new JButton("Next generation");
    playButton=new JButton("Play");
    nextButton.setPreferredSize(new Dimension(150,50));
    playButton.setPreferredSize(new Dimension(150,50));
    nextButton.addActionListener(this);
    playButton.addActionListener(this);
    frame.add(nextButton, BorderLayout.LINE_START);
    frame.add(playButton, BorderLayout.LINE_END);

    cellPanel=new JPanel();        
    cellPanel.setLayout(gridLayout);                                               //gives the panel a gridlayout
    cellPanel.setPreferredSize(new Dimension(600,600));
    frame.add(cellPanel, BorderLayout.PAGE_START);
    for(int i=0; i<100; i++){  
        cells[i%10][i/10]=new Cell();                                            //i/10 will be rounded down, so it equals the rownumber
        cellPanel.add(cells[i%10][i/10]);
        cells[i%10][i/10].addMouseListener(cells[i%10][i/10]);                   //add a mouselistener to the cell
        cells[i%10][i/10].setOpaque(true);                                       //makes the backgroundcolor visible
        cells[i%10][i/10].setBackground(Color.BLACK);
        cells[i%10][i/10].setBorder(BorderFactory.createLineBorder(Color.WHITE));

    }    

    frame.setVisible(true);
    for(int i=0; i<100; i++){  
        for(int j=0; j<9; j++){
            if((i%10-1+j%3>=0) && (i%10-1+j%3<10) && (i/10-1+j/3>=0) && (i/10-1+j/3<10) && !(j==4)){   //exclude cells that are outside the frame (non existant) and the cell itself  
                cells[i%10][i/10].setNeighbours(cells[i%10-1+j%3][i/10-1+j/3]);           //this adds all the neighbours to the arraylist
            }
        }
    }
}
public void actionPerformed(ActionEvent e){
    if(e.getSource()==nextButton){
        for(int i=0; i<100; i++){ 
            cells[i%10][i/10].calculateNextState(); 
        }
        for(int i=0; i<100; i++){  
            cells[i%10][i/10].updateToNextState();
        }
    }
    else{if (e.getSource()==playButton) {
      play = true;
      for (int p=0; p<3;p++) {

        for(int i=0; i<100; i++){ 
            cells[i%10][i/10].calculateNextState(); 
        }
        for(int i=0; i<100; i++){  
            cells[i%10][i/10].updateToNextState();
        }

    }

    }

    }
}

void readInput(){
    try{
        file = new File( filename);
        scanner = new Scanner( file );
        String nextGen="";                                                               //this string will contain the output
        int row=scanner.nextInt();                                                       //read the row number
        int col=scanner.nextInt();                                                       //and the column number
        Cell[][] cellen=new Cell[row][col];                                              //array containing all the cells
        for(int i=0; i<row*col; i++){
            cellen[i%row][i/col]=new Cell(); 
            if(scanner.next().equals(".")){
                cellen[i%row][i/col].setState(CellState.alive);                                     //set the state
            }
            else{
                cellen[i%row][i/col].setState(CellState.dead); 

            }

        }
        for(int i=0; i<row*col; i++){
            for(int j=0; j<9; j++){
                if((i%row-1+j%3>=0) && (i%row-1+j%3<row) && (i/col-1+j/3>=0) && (i/col-1+j/3<col) && !(j==4)){ 
                    cellen[i%row][i/col].setNeighbours(cellen[i%row-1+j%3][i/col-1+j/3]);            //set the neighbours
                }
            }
        }
        for(int i=0; i<row*col; i++){
            cellen[i%row][i/col].calculateNextState();                                  //calculate the next state for all the cells
        }
        for(int i=0; i<row*col; i++){
            cellen[i%row][i/col].updateToNextState();                                   //update all the cells to the next state
        }
        for(int i=0; i<row; i++){
            for(int j=0; j<col; j++){
                if(cellen[i%row][i/col].getCurrentState()==CellState.alive){                             //the cell is alive if getCurrentState is true
                    nextGen+="*";
                }
                else{
                    nextGen+=".";
                }
            }
            nextGen+=System.getProperty("line.separator");                              //add an enter after each row
        }
        System.out.println(nextGen);                                                    //print the next generation to the console
    }

    catch(FileNotFoundException e) {
        System.out.println( "Could not find or open file <"+filename+">\n"+e );         
    } 
}
public static void main(String[] args) {
    new GameOfLife().buildit();
}
}

我的问题是,当我尝试将计算保持无限次时 我的程序会冻结,如下面的代码所示

 else{if (e.getSource()==playButton) {
      play = true;
      for (int p=0; p<3;p++) {

        for(int i=0; i<100; i++){ 
            cells[i%10][i/10].calculateNextState(); 
        }
        for(int i=0; i<100; i++){  
            cells[i%10][i/10].updateToNextState();
        }

    }

    }

我只进行了3次计算,但是我希望它经过这些无限次,直到停止按钮(要创建的喷射),每次计算之间有1秒的暂停。我已经尝试了一段时间循环,但这只是冻结了我的应用程序 暂停和无限计算的一些帮助将非常有用

3 个答案:

答案 0 :(得分:1)

这里的问题是你的代码在Swing Event Dispatch Thread中运行,这意味着你正在做的所有必须在它回到像回复按钮之类的事情之前完成点击和绘图更改。

我建议你研究一下:

答案 1 :(得分:0)

正如其他人所评论的,你应该真正研究线程和同步。

线程允许您同时执行多项操作,而不需要循环以及什么不能阻止您的代码。编程需要同时执行多个任务的应用程序是一个重要方面。您可以了解线程here

同步保持一致性,并确保操作相同数据(变量,对象,等等)的多个线程将正确计算。您可以了解同步here

线程有一些参数,但最重要的是Runnable。您的Runnable将保留您希望线程运行的代码。您将Runnable传递给对象。有多种方法可以实现,但创建包含Runnable的Thread的两种最简单的方法是:

Runnable myRunnable = new Runnable() {
    public void run() {
        //your code here
    }
}

Thread thread = new Thread(myRunnable);

以及更常见的方式:

Thread thread = new Thread(new Runnable() {
    public void run() {

    }
});

现在,希望您对Threads有一点了解(我强烈建议您阅读Oracle的试用版),我们可以了解您想要做的事情。

您想要计算代码,在每次计算之间,您需要1秒的延迟。这是Thread.sleep()方法的用武之地。

Thread.sleep()允许您暂停线程一段时间。看看你想如何在每次计算之间做到这一点,你想把它放在实际代码的末尾(因为它将处于循环中)。

boolean running;

Thread thread = new Thread(new Runnable() {
    public void run() {
        while(running) {
            //calculation code

            Thread.sleep(1000); //counted in miliseconds
        }
    }
});

现在,正如我之前提到的,如果您想在包含UI的类之外操作UI,则必须使用SwingUtilities invokeLater()才能在UIThread中触发代码,但在外部班上的。此方法还将Runnable作为参数。

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        //code to manipulate frame/panel/applet
    }
});

BTW,Runnable被认为是功能接口功能接口是仅包含一个方法的接口。这是一些信息(从我看到的)未在接口试用版中列出,这就是我现在让你知道这个术语的原因。您可以查看接口here


boolean play = false;

public void actionPerformed(ActionEvent e) {
    if
    play = !play;

    if(play) {
        if(!thread.isAlive())
            thread.start();
    } else {
        if(thread.isAlive()) {
            thread.interrupt();
            try { thread.join(); }catch(InterruptedException e) { }
        }
    }
}

答案 2 :(得分:0)

简单的方法是将Thread.sleep(1000)放在循环中以使进度可见并仅使用SwingUtilities.invokeLater()更新UI。这不是一个非常漂亮的解决方案,但应该有效。