简体   繁体   English

如何为Tic Tac Toe GUI游戏制作正确的重启按钮?

[英]How do I make a proper restart button for my Tic Tac Toe GUI game?

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. 在第二场游戏后按下重新启动按钮将清除棋盘,但是当用户绘制“ O”或“ X”时,它们不会被吸引到棋盘上。 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);
    }
}

} }

You are removing and adding components during runtime. 您正在运行时删除和添加组件。 Where's your call to revalidate() ? 您在哪里致电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
        }

Try so restart action just resets the 9 Cells on the board and also resets the labels. 请尝试重新启动操作,仅重设板上的9个单元,并重设标签。
If you have any other "state" variables - they should also be re-initialized. 如果您还有其他“状态”变量-也应将其重新初始化。
I'd avoid calling panel.removeAll(); 我避免调用panel.removeAll();

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. 通过在我的构造函数中抛出一个setUpBoard方法,我可以将内部版本扔进去,然后在重新启动按钮中调用它。 Works great 效果很好

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

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