简体   繁体   English

生命游戏没有正确暂停

[英]Game of Life not pausing properly

I'm trying to make my version of game of life but I'm stuck trying to make use of Threads to give the program the ability to pause and resume.我正在尝试制作我的生活游戏版本,但我一直在尝试使用Threads来让程序能够暂停和恢复。

I use a Thread to execute the main Jpanel , where we can see the different generations, when I click on "pause" the screen successfully pauses but when it resumes 5 seconds later (because I use Thread.sleep(5000) ), I realize that the screen froze but the game was actually still running, it just wasn't updating the screen.我使用Thread来执行主Jpanel ,在那里我们可以看到不同的代,当我点击“暂停”时,屏幕成功暂停,但当它在 5 秒后恢复时(因为我使用Thread.sleep(5000) ),我意识到屏幕冻结但游戏实际上仍在运行,只是没有更新屏幕。

Like it pauses at generation #5 and resumes at generation #11, and obviously I want the game to resume right where it paused but I tried many things and so far nothing works.就像它在第 5 代暂停并在第 11 代恢复一样,显然我希望游戏在暂停的地方恢复,但我尝试了很多东西,但到目前为止没有任何效果。 Any help would be great.任何帮助都会很棒。

GameOfLife Class:生命游戏类:

public class GameOfLife extends JFrame implements ActionListener {

static JLabel aliveLabel = new JLabel("Alive:");
static JLabel GenerationLabel = new JLabel("Generation #");
static SimpleCellGrid body = new SimpleCellGrid();
static JPanel header = new JPanel();
static int genNumber = 1;
static JButton PlayToggleButton = new JButton("pause");
static JButton ResetButton = new JButton("b");
static Thread t1 = new Thread(body, String.valueOf(header));



public GameOfLife() throws IOException {
    super("Game of life");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(700, 660);
    setLocationRelativeTo(null);
    setLayout(new FlowLayout());

    GenerationLabel.setName("GenerationLabel");
    aliveLabel.setName("aliveLabel");
    PlayToggleButton.setName("PlayToggleButton");
    ResetButton.setName("ResetButton");

    PlayToggleButton.addActionListener(this);
    ResetButton.addActionListener(this);

    PlayToggleButton.setIcon(new ImageIcon(play));
    ResetButton.setIcon(new ImageIcon(reset));

    PlayToggleButton.setPreferredSize(new Dimension(40,30));
    ResetButton.setPreferredSize(new Dimension(40,30));

    header.setLayout(new FlowLayout());
    header.setPreferredSize(new Dimension(100, this.getHeight()));
    header.add(PlayToggleButton);
    header.add(ResetButton);
    header.add(GenerationLabel);
    header.add(aliveLabel);


    body.setLayout(new BorderLayout());
    body.setPreferredSize(new Dimension(500, this.getHeight()));

    add(header, BorderLayout.WEST);
    add(body, BorderLayout.CENTER);
    setVisible(true);

}

public static void updateLabels(){

    body.run();
    GenerationLabel.setText("Generation #"+ genNumber++);
    aliveLabel.setText("Alive: "+ body.totalAlive());

    try {
        Thread.sleep(100);
        updateLabels();
    } catch (InterruptedException ignore) { }
}

@Override
public void actionPerformed(ActionEvent e) {

    if(e.getActionCommand().equals("pause")){
        try {
            t1.sleep(5000);
            PlayToggleButton.setEnabled(true);

        } catch (InterruptedException ex) {
            t1.start();
        }

    }
}

public static void main(String[] args) throws IOException {
    new GameOfLife();
    updateLabels();
}
}

SimpleCellGrid class: SimpleCellGrid 类:

public class SimpleCellGrid extends JPanel implements Runnable{
private static final int ROWS = 50;
private static final int COLS = 50;
private static final int CELL_WIDTH = 10;
private static SimpleCell[][] cellGrid = new SimpleCell[ROWS][COLS];

public SimpleCellGrid() {
    for (int row = 0; row < cellGrid.length; row++) {
        for (int col = 0; col < cellGrid[row].length; col++) {
            int x = col * CELL_WIDTH;
            int y = row * CELL_WIDTH;
            cellGrid[row][col] = new SimpleCell(x, y, CELL_WIDTH);

            if (new Random().nextBoolean()) {
                cellGrid[row][col].setAlive(true);
            } else {
                cellGrid[row][col].setAlive(false);
            }
        }
    }
}
public int totalAlive(){
    int totalAlive = 0;
    for (SimpleCell[] simpleCells : cellGrid) {
        for (int j = 0; j < cellGrid.length; j++) {
            if (simpleCells[j].isAlive())
                totalAlive++;
        }
    }
    return totalAlive;
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    for (SimpleCell[] cellRow : cellGrid) {
        for (SimpleCell simpleCell : cellRow) {
            simpleCell.draw(g2);
        }
    }
}

@Override
public void run() {
    cellGrid = new GenerationMaker4().nextGeneration(cellGrid);
    repaint();
}
}

Sleeping a thread is not what you'll need here.在这里睡一个线程不是你所需要的。

To pause your game, re-factor the code so that you have a core game method that performs the game progression by a unit every time it is run.要暂停您的游戏,请重构代码,以便您拥有一个核心游戏方法,该方法在每次运行时按一个单元执行游戏进程。 You can schedule this core game method to run at a regular rate with a java.util.TimerTask .您可以使用java.util.TimerTask安排此核心游戏方法以常规速率运行。 When you want to pause your game simply stop the TimerTask from running the core game method, and when you un-pause, start running it again.当你想暂停你的游戏时,只需停止 TimerTask 运行核心游戏方法,当你取消暂停时,再次开始运行它。

This way, your program will remain responsive 100% of the time.这样,您的程序将在 100% 的时间内保持响应。

You called updateLabels() using your main thread.您使用主线程调用了updateLabels()

You called Thread.sleep(5000) using your t1 thread.您使用 t1 线程调用了Thread.sleep(5000)

main thread will continue to run while t1 sleeps.主线程将在 t1 休眠时继续运行。

Refer to https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html on how to start a thread instead of calling run manually.有关如何启动线程而不是手动调用run请参阅https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html

Try to use really simple small program to test out concepts.尝试使用非常简单的小程序来测试概念。 In your learning effort above, you mixed multithreading with UI programming and recursion which could make things hard for you在上面的学习工作中,您将多线程与 UI 编程和递归混合在一起,这可能会让您感到困难

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM