【问题标题】:Game of Life not pausing properly生命游戏没有正确暂停
【发布时间】:2020-02-05 03:00:12
【问题描述】:

我正在尝试制作我的人生游戏版本,但我一直在尝试使用 Threads 让程序能够暂停和恢复。

我使用Thread 来执行主要的Jpanel,在这里我们可以看到不同的世代,当我点击“暂停”时,屏幕成功暂停,但当它在 5 秒后恢复时(因为我使用 Thread.sleep(5000) ),我意识到屏幕冻结了,但游戏实际上仍在运行,只是没有更新屏幕。

就像它在第 5 代暂停并在第 11 代恢复一样,显然我希望游戏从暂停的地方恢复,但我尝试了很多东西,但到目前为止没有任何效果。任何帮助都会很棒。

GameOfLife 类:

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 类:

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();
}
}

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    在这里你不需要休眠线程。

    要暂停您的游戏,请重构代码,以便您拥有一个核心游戏方法,该方法在每次运行时按一个单位执行游戏进程。您可以使用java.util.TimerTask 安排此核心游戏方法以常规速率运行。当您想暂停游戏时,只需停止 TimerTask 运行核心游戏方法,当您取消暂停时,再次开始运行它。

    这样,您的程序将保持 100% 的响应时间。

    【讨论】:

    • 看起来很辛苦,因为我还在学习这一切,但它奏效了,非常感谢:)
    • 没问题,我很高兴听到您努力转换源代码。没有多少人会努力自己学习新事物。它应该对你的未来有好处。当有更多需要学习的东西时,永远不要害怕提出问题。 :)
    • 再次感谢,您的评论增强了我的信心。努力和努力永远不会浪费时间。
    【解决方案2】:

    您使用主线程调用了updateLabels()

    您使用您的 t1 线程调用了Thread.sleep(5000)

    主线程将在 t1 休眠时继续运行。

    关于如何启动线程而不是手动调用run,请参阅https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html

    尝试使用非常简单的小程序来测试概念。在您上面的学习工作中,您将多线程与 UI 编程和递归混合在一起,这可能会让您感到困难

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-09
      • 1970-01-01
      • 2015-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多