Search code examples
javamultithreadingswinganimationtic-tac-toe

How to pause / resume Java Threads


I am making a Tic Tac Toe Program in java because i am learning java and i thought a simple project would be a great place to start. This is my code so far:

public class Start {
    public static void main(String[] args) {
    GameTicTacToe gameTicTacToe = new GameTicTacToe();
    gameTicTacToe.windowBirth();

    }
}

And,

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class GameTicTacToe implements ActionListener {
    private int gridSize = 3;
    private JButton[] gridButton = new JButton[(gridSize * gridSize)];
    private JPanel grid = new JPanel(new GridLayout(gridSize, gridSize, 0, 0));
    private JFrame windowTicTacToe = new JFrame("Tisk, Task, Toes");
    private int[] gridButtonOwner = new int[(gridSize * gridSize)];
    private int turn = 1;
    private int HolerHor, HolerVer, HolerDia1, HolerDia2;

    Thread winnerBlue = new Thread() {
        public void run() {
            for (int a = 0; a < 4; a++) {
                for (int i = 0; i < gridButton.length; i++) {
                    gridButton[i].setBackground(Color.BLUE);
                }
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                }
                for (int i = 0; i < gridButton.length; i++) {
                    gridButton[i].setBackground(Color.WHITE);
                }
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                }
            }
            for (int i = 0; i < gridButton.length; i++) {
                gridButton[i].setEnabled(true);
                gridButtonOwner[i] = 0;
            }
        }
    };
    Thread winnerRed = new Thread() {
        public void run() {
            for (int a = 0; a < 4; a++) {
                for (int i = 0; i < gridButton.length; i++) {
                    gridButton[i].setBackground(Color.RED);
                }
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                }
                for (int i = 0; i < gridButton.length; i++) {
                    gridButton[i].setBackground(Color.WHITE);
                }
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                }
            }
            for (int i = 0; i < gridButton.length; i++) {
                gridButton[i].setEnabled(true);
                gridButtonOwner[i] = 0;
            }
        }
    };
    public void windowBirth() {
        for (int i = 0; i < gridButton.length; i++) {
            gridButtonOwner[i] = 0;
            gridButton[i] = new JButton("");
            gridButton[i].addActionListener(this);
            gridButton[i].setBackground(Color.WHITE);
            grid.add(gridButton[i]);
        }
        windowTicTacToe.setDefaultCloseOperation(3);
        windowTicTacToe.setLocation(400, 200);
        windowTicTacToe.setPreferredSize(new Dimension(400, 400));
        windowTicTacToe.add(grid);
        windowTicTacToe.pack();
        windowTicTacToe.setVisible(true);
    }
    public void actionPerformed(ActionEvent gridButtonClicked) {
        for (int i = 0; i < gridButton.length; i++) {
            if (gridButtonClicked.getSource() == gridButton[i]) {
                if (turn == 1) {
                    turn = 2;
                    gridButtonOwner[i] = 1;
                    gridButton[i].setBackground(Color.blue);
                    gridButton[i].setEnabled(false);
                } else {
                    turn = 1;
                    gridButtonOwner[i] = 2;
                    gridButton[i].setBackground(Color.red);
                    gridButton[i].setEnabled(false);
                }
            }
        }
        checkWinner();
    }
    public void checkWinner() {
        for (int a = 1; a < 3; a++) {
            HolerDia1 = a;
            HolerDia2 = a;
            for (int b = 0; b < gridSize; b++) {
                HolerHor = a;
                HolerVer = a;
                for (int c2 = 0; c2 < gridSize; c2++) {
                    HolerHor = (HolerHor * gridButtonOwner[((b * gridSize) + c2)])/ a;
                    HolerVer = (HolerVer * gridButtonOwner[((c2 * gridSize) + b)])/ a;
                }
                if (HolerHor == a || HolerVer == a) {
                    winnerAnimation(a);
                }
            }
            for(int h = 0;h < gridSize; h++){
                HolerDia1 = (HolerDia1 * gridButtonOwner[h * (gridSize + 1)]) / a;
                HolerDia2 = (HolerDia2 * gridButtonOwner[(h * (gridSize - 1)) + (gridSize - 1)]) / a;
            }
            if (HolerDia1 == a || HolerDia2 == a) {
                winnerAnimation(a);
            }
        }
    }
    public void winnerAnimation(int b) {
        for (int i = 0; i < gridButton.length; i++) {
            gridButton[i].setEnabled(false);
        }
        if (b == 1){
            winnerBlue.start();
        }else{
            winnerRed.start();
        }
    }
}

This is my question, When a player wins, for example Player 1 (Blue), it plays the animation (Flashing the board Blue). But when Player 1 wins again, the program crashes.

I looked into it a little and found that you can't start a thread twice because you just can't.

How would i go about pausing the thread, then restarting it when i need to?


Solution

  • You could simply create a new Thread and run it when needed. But regardless of this, I'd do the animation using a Swing Timer as it's simpler and safer since you don't have to worry about pernicious intermittent crashes from accidently stepping on the Swing thread, the EDT.

    For e.g.,

       public void myWinner(final Color flashColor) {
          int timerDelay = 300;
          new javax.swing.Timer(timerDelay , new ActionListener() {
             private static final int COUNTER_MAX = 5;
             int counter = 0;
    
             public void actionPerformed(ActionEvent e) {
                if (counter >= COUNTER_MAX) { // time to stop
                   ((Timer)e.getSource()).stop();
                   for (int i = 0; i < gridButton.length; i++) {
                      gridButton[i].setBackground(Color.white); // just to be sure
                      gridButton[i].setEnabled(true);
                      gridButtonOwner[i] = 0;
                   }
                }
                Color bckgrndColor = (counter % 2 == 0) ? flashColor : Color.white;
                for (JButton button : gridButton) {
                   button.setBackground(bckgrndColor);
                }
                counter++;
             }
          }).start();
       }