Reputation: 13
I currently have a restart button that only restarts correctly if the first game is finished. Hitting the restart button after a second game clears the board, but when the user goes to draw a "O" or an "X", they are not drawn to the board. I really want a fully functional restart button, but I am unsure on how to create it.
// JFrame for klTicTacToe board.
public class GameClass extends JFrame {
// Indicate whose turn it is
private char whoseTurn = 'X';
// Cell grid 9 cells
private Cell[][] cells = new Cell[3][3];
// status label
JLabel introLabel = new JLabel("Welcome to Tic Tac Toe! X Goes First");
// restart button
JButton restart = new JButton("Restart");
// Game constructor
public GameClass() {
// Panel to hold cells
JPanel panel = new JPanel(new GridLayout(3, 3, 0, 0));
for (int i = 0; i < 3; i++)
for (int f = 0; f < 3; f++)
panel.add(cells[i][f] = new Cell());
panel.setBorder(new LineBorder(Color.BLACK, 5));
introLabel.setBorder(new LineBorder(Color.BLACK, 2));
introLabel.setFont(new Font("Times New Roman", Font.PLAIN, 20));
introLabel.setForeground(Color.DARK_GRAY);
restart.setBackground(Color.GREEN);
// Restart button action listener
restart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == restart) {
panel.removeAll();
// re establishes cell layout
// Panel to hold cells
JPanel panel = new JPanel(new GridLayout(3, 3, 0, 0));
for (int i = 0; i < 3; i++)
for (int f = 0; f < 3; f++)
panel.add(cells[i][f] = new Cell());
panel.setBorder(new LineBorder(Color.BLACK, 5));
introLabel.setBorder(new LineBorder(Color.BLACK, 2));
introLabel.setFont(new Font("Times New Roman", Font.PLAIN, 20));
introLabel.setForeground(Color.DARK_GRAY);
add(panel, BorderLayout.CENTER);
add(introLabel, BorderLayout.NORTH);
add(restart, BorderLayout.SOUTH);
introLabel.setText("New Game! X goes First");
}
}
});
add(panel, BorderLayout.CENTER);
add(introLabel, BorderLayout.NORTH);
add(restart, BorderLayout.SOUTH);
}
// Determines if True, if game board is full. Otherwise, false.
public boolean isFull() {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (cells[i][j].getToken() == ' ')
return false;
return true;
}
// Determines if a given token has won.
// Token to test for winning True, if the token has won. Otherwise, false.
public boolean isWon(char gameToken) {
// check rows
for (int i = 0; i < 3; i++)
if ((cells[i][0].getToken() == gameToken) && (cells[i][1].getToken() == gameToken)
&& (cells[i][2].getToken() == gameToken)) {
return true;
}
// check columns
for (int j = 0; j < 3; j++)
if ((cells[0][j].getToken() == gameToken) && (cells[1][j].getToken() == gameToken)
&& (cells[2][j].getToken() == gameToken)) {
return true;
}
// check diagonal
if ((cells[0][0].getToken() == gameToken) && (cells[1][1].getToken() == gameToken)
&& (cells[2][2].getToken() == gameToken)) {
return true;
}
if ((cells[0][2].getToken() == gameToken) && (cells[1][1].getToken() == gameToken)
&& (cells[2][0].getToken() == gameToken)) {
return true;
}
return false;
}
Rest of code:
// Defines a cell in a TicTacToe game board.
public class Cell extends JPanel
// token of this cell
private char token = ' ';
// Cell constructor
public Cell() {
setBorder(new LineBorder(Color.black, 5));
addMouseListener(new MyMouseListener());
}
// Gets the token of the cell.
public char getToken() {
return token;
}
// Sets the token of the cell.
// Character to use as token value.
public void setToken(char f) {
token = f;
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Draws "X" and "O"
if (token == 'X') {
Graphics2D g2 = (Graphics2D) g;
g.setColor(Color.BLUE);
g2.setStroke(new BasicStroke(5));
g.drawLine(10, 10, getWidth() - 10, getHeight() - 10);
g.drawLine(getWidth() - 10, 10, 10, getHeight() - 10);
}
else if (token == 'O') {
Graphics2D g2 = (Graphics2D) g;
g.setColor(Color.RED);
g2.setStroke(new BasicStroke(5));
g.drawOval(10, 10, getWidth() - 20, getHeight() - 20);
}
}
private class MyMouseListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
// if the cell is empty and the game is not over
if (token == ' ' && whoseTurn != ' ')
setToken(whoseTurn);
// Check game status
if (isWon(whoseTurn)) {
introLabel.setText(whoseTurn + " has won! Game over! Press Restart to Play Again");
whoseTurn = 'X';
} else if (isFull()) {
introLabel.setText("Tie game! Game over! Press Restart to Play Again");
whoseTurn = ' ';
} else {
whoseTurn = (whoseTurn == 'X') ? 'O' : 'X';
introLabel.setText(whoseTurn + "'s turn.");
}
}
}
}
// Driver Class for Tic Tac Toe
public class TicTacToeGame {
public void main(String[] args) {
JFrame ticTacToe = new GameClass();
ticTacToe.setTitle("TicTacToe Game");
ticTacToe.setSize(700, 700);
ticTacToe.setLocationRelativeTo(null);
ticTacToe.setVisible(true);
ticTacToe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
}
Upvotes: 1
Views: 1653
Reputation: 13
Okay, so I just figured it out. By throwing a setUpBoard method in my constructor, I was able to throw the build inside of it and then call it from within the restart button. Works great
Upvotes: 0
Reputation: 2147
Try so restart action just resets the 9 Cells on the board and also resets the labels.
If you have any other "state" variables - they should also be re-initialized.
I'd avoid calling panel.removeAll();
Upvotes: 0
Reputation: 12332
You are removing and adding components during runtime. Where's your call to revalidate()
? Try the below:
if (e.getSource() == restart) {
panel.removeAll();
// re establishes cell layout
// Panel to hold cells
JPanel panel = new JPanel(new GridLayout(3, 3, 0, 0));
for (int i = 0; i < 3; i++)
for (int f = 0; f < 3; f++)
panel.add(cells[i][f] = new Cell());
panel.setBorder(new LineBorder(Color.BLACK, 5));
introLabel.setBorder(new LineBorder(Color.BLACK, 2));
introLabel.setFont(new Font("Times New Roman", Font.PLAIN, 20));
introLabel.setForeground(Color.DARK_GRAY);
add(panel, BorderLayout.CENTER);
add(introLabel, BorderLayout.NORTH);
add(restart, BorderLayout.SOUTH);
introLabel.setText("New Game! X goes First");
revalidate(); // <-- add this
}
Upvotes: 1