Java,15个益智游戏的倒计时器?请帮助我理解计时器

标签 java swing timer jlabel countdown

在开始之前,我想解释一下,我已经看过许多其他类似的问题以及网上的许多视频,但它们都无法帮助我理解计时器的工作原理或我将如何为自己创建一个计时器,希望没有人认为这是一个不必要的帖子。

我不明白延迟的用途,我很想了解有关计时器及其使用方式的所有内容。

所以我正在创建一个 15 谜题游戏,游戏已经完成,但我想添加另一个功能。

显示在 JLabel 上的计时器。 具体内容:

  1. 计时器从 5 分钟或 10 分钟开始倒计时。
  2. 想要计时器的格式“mm:ss”。
  3. 一旦按下第一个按钮,计时器就会开始计时 倒计时。
  4. 如果在计时器耗尽之前解决,您就赢了,否则您就输了。
  5. 如果您按“新游戏”按钮,它会重置为 5 或 10 分钟。
  6. 一旦您按下游戏中的第一个按钮,倒计时就会再次开始。

如果您能解释一下这些参数的用途以及我应该在我的案例中使用什么计时器,我会很高兴。我也在使用 java swing。

如果您有兴趣,这是迄今为止我的游戏:

class GameLogic extends JFrame implements ActionListener {

private JPanel grid = new JPanel();
private JPanel overHead = new JPanel();
private JButton newGameButton = new JButton("NEW GAME");
private JButton[][] buttons = new JButton[4][4];
private JButton[][] winPattern = new JButton[4][4];
private JButton button0 = new JButton("");
private JLabel timerLabel = new JLabel("TIMER");
private int emptyIndex;
private int sourceIndex;
private int sourceRow;
private int sourceCol;
private int blankRow;
private int blankCol;
private int movesCounter = 0;
private JLabel movesLabel = new JLabel("MOVES");

public GameLogic() {
    setLayout(new BorderLayout());
    add(overHead, BorderLayout.NORTH);
    overHead.setLayout(new BorderLayout());
    overHead.add(newGameButton, BorderLayout.WEST);
    overHead.add(movesLabel, BorderLayout.EAST);
    overHead.add(timerLabel, BorderLayout.CENTER);
    movesLabel.setFont(new Font("Street Cred", Font.PLAIN, 20));
    newGameButton.setPreferredSize(new Dimension(100, 50));
    newGameButton.setFont(new Font("Street Cred", Font.PLAIN, 13));
    overHead.setBorder(new EmptyBorder(50, 50, 10, 50));
    grid.setBorder(new EmptyBorder(50, 50, 50, 50));
    newGameButton.addActionListener(this);
    add(grid, BorderLayout.CENTER);
    setBackground(Color.RED);
    grid.setLayout(new GridLayout(4, 4));
    try {
        GraphicsEnvironment ge =
                GraphicsEnvironment.getLocalGraphicsEnvironment();
        ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, new File("street cred.ttf")));
    } catch (IOException | FontFormatException e) {
        //Handle exception
    }
    int i = 1;
    for (int row = 0; row < buttons.length; row++) {
        for (int col = 0; col < buttons.length; col++) {
            if (row == 3 && col == 3) {
                buttons[row][col] = button0;
                grid.add(buttons[row][col]);
                buttons[row][col].setBackground(Color.WHITE);
                buttons[row][col].setName("button0");
                winPattern[row][col] = button0;
            } else {
                buttons[row][col] = new JButton(i + "");
                grid.add(buttons[row][col]);
                buttons[row][col].addActionListener(this);
                buttons[row][col].setBackground(Color.RED);
                buttons[row][col].setName("button" + i);
                buttons[row][col].setFont(new Font("Street Cred", Font.PLAIN, 40));
                winPattern[row][col] = buttons[row][col];
                i++;
            }
        }
    }

    do {
        shuffle();
    } while (!isSolvable());
    try {
        setIconImage(ImageIO.read(new File("C:\\Users\\Allan\\Documents\\Nackademin\\OOP\\test2\\icon.png")));
    } catch (IOException e) {
        e.printStackTrace();
    }
    movesLabel.setText("<html>MOVES<br><html>" + "----- " + movesCounter + " -----");
    setTitle("PUZZLE GAME");
    setCursor(new Cursor(Cursor.HAND_CURSOR));
    setResizable(false);
    setLocation(500, 200);
    setSize(600, 600);
    setVisible(true);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
}

public boolean isSolvable() {
    int inv_counter = 0;
    int[] values = new int[16];
    // Lägger alla komponenters nummer i en int array
    for (int i = 0; i < grid.getComponents().length; i++) {
        if (grid.getComponents()[i] == button0) {
            values[i] = 0;
        } else {
            JButton temp = (JButton) grid.getComponents()[i];
            values[i] = Integer.parseInt(temp.getText());
        }

    }

    for (int i = 0; i < values.length - 1; i++) {
        for (int j = i + 1; j < values.length; j++) {
            if (values[i] < values[j]) {
                inv_counter++;
            }
        }
    }

    return inv_counter % 2 == 0;
}


public boolean isSwappable(JButton button) {

    // för att hitta platsen på knappen man trycker och även den blanka platsen
    for (int row = 0; row < buttons.length; row++) {
        for (int col = 0; col < buttons.length; col++) {
            if (buttons[row][col] == button) {
                sourceRow = row;
                sourceCol = col;
            } else if (buttons[row][col] == button0) {
                blankRow = row;
                blankCol = col;
            }
        }
    }
    sourceIndex = (sourceRow * 4) + sourceCol;
    emptyIndex = (blankRow * 4) + blankCol;
    // om den är till höger
    if (sourceCol != 3 && sourceRow == blankRow && buttons[sourceRow][sourceCol + 1] == button0) {
        return true;
    }
    // om den är till vänster
    else if (sourceCol != 0 && sourceRow == blankRow && buttons[blankRow][sourceCol - 1] == button0) {
        return true;
    }
    //om den är nedanför
    else if (sourceRow != 0 && sourceCol == blankCol && buttons[sourceRow - 1][sourceCol] == button0) {
        return true;
    }
    //om den är ovanför
    else if (sourceRow != 3 && sourceCol == blankCol && buttons[sourceRow + 1][sourceCol] == button0) {
        return true;
    }
    return false;
}

public void swap(JButton source) {
    JButton tempButton = buttons[sourceRow][sourceCol];
    buttons[sourceRow][sourceCol] = buttons[blankRow][blankCol];
    buttons[blankRow][blankCol] = tempButton;
    grid.remove(button0);
    grid.remove(source);

    if (emptyIndex < sourceIndex) {
        grid.add(source, emptyIndex);
        grid.add(button0, sourceIndex);
    } else if (emptyIndex > sourceIndex) {
        grid.add(button0, sourceIndex);
        grid.add(source, emptyIndex);
    }
    revalidate();
    repaint();
}

public void shuffle() {
    Random random = new Random();

    //randomize positions for 2D array buttons
    for (int row = 0; row < buttons.length; row++) {
        for (int col = 0; col < buttons.length; col++) {
            int randomNumber = random.nextInt(16);
            int randomRow = randomNumber / 4;
            int randomCol = randomNumber % 4;
            JButton temp = buttons[row][col];
            buttons[row][col] = buttons[randomRow][randomCol];
            buttons[randomRow][randomCol] = temp;
        }
    }
    //remove all components from panel
    grid.removeAll();

    // add components with randomized position to panel
    for (int row = 0; row < buttons.length; row++) {
        for (int col = 0; col < buttons.length; col++) {
            grid.add(buttons[row][col]);
        }
    }
    revalidate();
    repaint();
}

public boolean isSolved() {
    int counter = 0;
    for (int row = 0; row < buttons.length; row++) {
        for (int col = 0; col < buttons.length; col++) {
            if (winPattern[row][col].getText().equals(buttons[row][col].getText())) {
                counter++;
            }
        }
    }
    if (counter == 16) {
        return true;
    } else {
        return false;
    }
}

public void moves() {
    movesCounter++;
    movesLabel.setText("<html>MOVES<br><html>" + "----- " + movesCounter + " -----");
}

public void timerCountDown() {
}

public void reset() {
    movesCounter = 0;
    movesLabel.setText("<html>MOVES<br><html>" + "----- " + movesCounter + " -----");
}

public void newGame() {
    do {
        shuffle();
        reset();
    } while (!isSolvable());
}

@Override
public void actionPerformed(ActionEvent e) {
    JButton source = (JButton) e.getSource();

    if (source == newGameButton) {
        newGame();
    } else if (isSwappable(source)) {
        swap(source);
        moves();
    }

    if (isSolved()) {
        JOptionPane.showMessageDialog(null, "YOU BEAT THE GAME!\nMoves: " + movesCounter + "\nTime: ");
        newGame();
    }
}
}

最佳答案

您可以使用 ScheduledExecutorService ( https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html )

它们允许您在精确的时刻运行任务(在您的例子中是计时器),并在给定的延迟后重复该任务。

创建 ScheduledExecutorService :

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

然后你需要运行你的任务,包括延迟和周期:

ScheduledFuture<?> handler = scheduler.scheduleAtFixedRate(yourTask, 0, 1, TimeUnit.SECONDS);

“yourTask”是一个可运行的。您可以使用 lambda,例如 () -> System.out.println("BEEP")或方法引用,例如 this::run ,带有一个运行方法,可以在屏幕上显示时间。您可以有两个字段 minutesseconds最初设置为 50 (或者您想要 10 分钟的 10 和 0 , that you would change every time the run` 方法被调用,然后在屏幕上显示正确的时间:

private void run(){
    seconds--;
    if(seconds < 0) {
        minutes--;
        seconds = 59;
    }
    displayTimeOnScreen();

    if(minutes == 0 && seconds == 0) {
        handler.cancel(true);
    }
}

您可以使用handler.cancel(true)停止任务。

关于Java,15个益智游戏的倒计时器?请帮助我理解计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58605386/

相关文章:

java - 将 ViewPort 添加到 JPanel

javascript - 如何为图像设置计时器以在 javascript 或 html 中显示?

c# - 可靠地停止 System.Threading.Timer?

java - 为什么我的 EJB3,1 计时器在两个服务器实例上运行?

java - 如何以某种格式向 JFrame 添加许多组件

java - 如何使用deque进行线程通信?

java - Mac OS X 上 IntelliJ IDEA 中的 JDK 文档

swing - 将外部文件拖入 Swing 应用程序时设置自定义光标

java - 缺少 GUI 输出

Java 在文本区域右侧显示文本