0

您好,我有这段代码,您可以在其中单击几个立方体以将它们设置为死或活,并根据一组规则,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 秒的暂停。我已经尝试了一个while循环,但这只是冻结了我的应用程序对于暂停和无限计算的一些帮助将非常有用

4

3 回答 3

1

这里的问题是您的代码在Swing Event Dispatch Thread中运行,这意味着您所做的一切都必须在它返回执行诸如响应按钮单击和绘图更改之类的操作之前完成。

我建议你调查一下:

于 2013-10-23T23:15:16.997 回答
0

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

线程允许你同时做多件事情,没有循环和什么不会阻碍你的代码。对于需要同时执行多项任务的应用程序编程来说,这是一个重要方面。你可以在这里了解线程

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

线程有一些参数,但最重要的是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() {

    }
});

现在,希望您对线程有更好的了解(我强烈建议您阅读 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
    }
});

顺便说一句,Runnable 被认为是一个功能接口功能接口是只包含一种方法的接口。这是接口试用版中未列出的一些信息(据我所知),这就是我现在让您知道该术语的原因。你可以在这里查看接口


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) { }
        }
    }
}
于 2013-10-23T23:16:59.423 回答
0

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

于 2013-10-23T23:19:01.990 回答