如何重置GUI和游戏?

时间:2018-08-14 21:59:04

标签: java swing oop user-interface jbutton

我正在制作一个游戏,并且想在游戏结束并单击“休息”按钮后重置游戏板。目前,该游戏的首次运行效果不错。

我认为问题出在重置方法“ this.play()”中。有人可以给我解释一下这是怎么回事。

使用“ this.play()”时,GUI不会重置,游戏也不会播放。没有“ this.play()”,GUI会重置,但游戏无法正常工作。

我还想在每次单击按钮后而不是循环后运行check方法。我不断收到错误消息,指出不能从静态上下文中引用非静态方法。我一直在把check方法放在按钮类的actionPerformed方法中

这是我的代码...

董事会课程...

public class ticTacBoard extends JFrame implements ActionListener
{
Toebuttons toe[] = new Toebuttons[9];
JFrame over = new JFrame("Game Over");
JPanel panel = new JPanel();
JLabel winner = new JLabel("");
static boolean win = false;
public static void start()
{ 
    ticTacBoard b = new ticTacBoard();
    b.play();
}
public void play()
{
    //ticTacBoard one = new ticTacBoard();
    while(!win && Toebuttons.count < 9)
    {
        this.check();
    }
    endFrame();
}

public ticTacBoard()
{
    super("Tic tac board");
    toFront();
    setSize(500,500);
    setLayout(new GridLayout(3,3));
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    for(int i = 0; i<toe.length; i++)
    {
        toe[i] = new Toebuttons();
        add(toe[i]);
    }
    setVisible(true);
}

public void check()
{
    checkRow();
    checkDiagonal();
    checkColumn();
}

public void checkRow()
{

    if((toe[0].getText().equals("X")||toe[0].getText().equals("O"))&&(toe[0].getText().equals(toe[1].getText()) && toe[1].getText().equals(toe[2].getText())))
    {
        winner.setText(toe[2].getText()+" WINS!!!\nROW");
        win = true;
    }
    if((toe[3].getText().equals("X")||toe[3].getText().equals("O"))&&(toe[3].getText().equals(toe[4].getText()) && toe[4].getText().equals(toe[5].getText())))
    {
        winner.setText(toe[3].getText()+" WINS!!!\nROW");
        win = true;
    }
    if((toe[6].getText().equals("X")||toe[6].getText().equals("O"))&&(toe[6].getText().equals(toe[7].getText()) && toe[7].getText().equals(toe[8].getText())))
    {
        winner.setText(toe[6].getText()+" WINS!!!\nROW");
        win = true;
    }
}

public void checkDiagonal()
{
    if((toe[0].getText().equals("X")||toe[0].getText().equals("O"))&&(toe[0].getText().equals(toe[4].getText()) && toe[4].getText().equals(toe[8].getText())))
    {
        winner.setText(toe[0].getText()+" WINS!!!\nDIAGONAL");
        win = true;
    }
    if((toe[2].getText().equals("X")||toe[2].getText().equals("O"))&&(toe[2].getText().equals(toe[4].getText()) && toe[4].getText().equals(toe[6].getText())))
    {
        winner.setText(toe[0].getText()+" WINS!!!\nDIAGONAL");
        win = true;
    }
}

public void checkColumn()
{
    if((toe[0].getText().equals("X")||toe[0].getText().equals("O"))&&(toe[0].getText().equals(toe[3].getText()) && toe[3].getText().equals(toe[6].getText())))
    {
        winner.setText(toe[0].getText()+" WINS!!!\nCOLUMN");
        win = true;
    }
    if((toe[1].getText().equals("X")||toe[1].getText().equals("O"))&&(toe[1].getText().equals(toe[4].getText()) && toe[4].getText().equals(toe[7].getText())))
    {
        winner.setText(toe[1].getText()+" WINS!!!\nCOLUMN");
        win = true;
    }
    if((toe[2].getText().equals("X")||toe[2].getText().equals("O"))&&(toe[2].getText().equals(toe[5].getText()) && toe[5].getText().equals(toe[8].getText())))
    {
        winner.setText(toe[2].getText()+" WINS!!!\nCOLUMN");
        win = true;
    }
}
public void endFrame()
{
    System.out.println("2222");
    over.setLocationRelativeTo(null);
    panel.setLayout(new FlowLayout());
    over.setLayout(new FlowLayout());
    panel.add(winner);
    panel.repaint();
    over.add(panel);
    over.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    over.setSize(500,100);
    JButton r = new JButton("Reset");
    JPanel p = new JPanel();
    p.add(r);
    over.add(p);
    r.addActionListener(this);
    over.repaint();
    over.setVisible(true);
}
public void reset()
{
    Toebuttons.x = true;
    for(int i = 0; i<toe.length;i++)
    { 
        toe[i].setText("blank");
    }
    win = false;
    Toebuttons.count = 0;
    this.play();
}
public void actionPerformed(ActionEvent e)
{
    over.hide();
    reset();
}
}

按钮类...

 public class Toebuttons extends JButton implements ActionListener
 {
 static boolean x = true;// if true x's turn if false o's turn
 public static int count = 0; 
 public Toebuttons()
 {
   super("blank");
   this.addActionListener(this);
 }
  public void actionPerformed(ActionEvent e)
 {
   if(this.x == true && getText().equals("blank") && !ticTacBoard.win)
   {
       count++;
       System.out.println(count);
       setText("X");
       this.x = false;
   }
   else if(this.x == false && getText().equals("blank")&& !ticTacBoard.win)
   {
       count++;
       System.out.println(count);
       setText("O");
       this.x = true;
   }

   }
   }

1 个答案:

答案 0 :(得分:1)

  

使用“ this.play()”时,GUI不会重置,游戏也不会播放。没有“ this.play()”,GUI会重置,但游戏无法正常工作。

问题是,您正在阻止事件调度线程...

public void play()
{
    //ticTacBoard one = new ticTacBoard();
    while(!win && Toebuttons.count < 9)
    {
        this.check();
    }
    endFrame();
}

这正在创建一个无限循环,该循环将阻止事件调度线程处理事件队列。

  

但是为什么它第一次起作用?

因为您实际上违反了GUI开发的基本规则之一。 main被调用,通常称为“主线程”。这意味着,第一次调用play时,您正在运行与事件调度线程不同的线程。但是,第二次调用它时,在EDT上下文中调用了reset,这将导致play对其进行阻止。

GUI开发的一些基本规则:

  • 请勿在UI线程内执行长时间运行或阻止操作
  • 不要从UI线程的上下文外部更新UI或UI依赖的状态。大多数UI API都不是线程安全的。

这是一个很大的主题,有些复杂,但是,您可以先通读Concurrency in Swing

  

那么,解决方案是什么?

UI是事件驱动的,您应该使用此机制来监视按钮状态何时更改,然后执行更新检查。

首先,摆脱play

第二,在板上的所有按钮上附加一个ActionListener。作为“操作”的一部分,您应该检查剧本的状态,并决定应该做什么。

而且,不,我不是说将支票添加到Toebuttons#actionPerformed中,我的意思是ticTacBoard应该在ActionListener上注册自己的Toebuttons并在触发时检查游戏状态-请注意,ActionListener的顺序称为我的效果,即您的决策过程,这就是为什么最好将UI状态与游戏状态分开的原因-但这就是另一个主题

概念上可运行的示例...

这是一个概念性示例,它引入了将UI与游戏状态分离的概念,并使UI仅负责显示游戏状态。

请参阅:

浏览它,放入一些System.out.println语句,然后对代码运行调试器。返回链接的教程,并扩展您对提出的概念的理解

虽然有些人可能认为它是“高级的”,但从概念上讲,它引入了您需要理解的核心概念,以便与一般的Swing和GUI一起使用

import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TicTac {

    public static void main(String[] args) {
        new TicTac();
    }

    public TicTac() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TicTacToePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public enum Player {
        X, O, NONE;
    }

    public interface TicTacToeModelListener {

        public void ticTacToeGameWon(TicTacToeModel model);
    }

    public class TicTacToeModel {

        private Player[] board;
        private Player turn;
        private Player winner;

        private List<TicTacToeModelListener> listeners;

        public TicTacToeModel() {
            board = new Player[3 * 3];
            listeners = new ArrayList<>(25);
            reset();
        }

        public boolean isX() {
            return turn == Player.X;
        }

        public void nextTurn() {
            if (isX()) {
                turn = Player.O;
            } else {
                turn = Player.X;
            }
        }

        public Player getTurn() {
            return turn;
        }

        public Player getWinner() {
            return winner;
        }

        public void reset() {
            for (int index = 0; index < board.length; index++) {
                board[index] = Player.NONE;
            }
            turn = Player.X;
            winner = Player.NONE;
        }

        public void set(int col, int row) {
            int index = (row * 3) + col;
            if (board[index] == Player.NONE) {
                board[index] = turn;
            } else {
                System.out.println("!! Spot already occupied");
            }

            check();
        }

        public void check() {
            checkRow();
            checkDiagonal();
            checkColumn();

            if (winner != Player.NONE) {
                fireGameWon();
            }
        }

        public void addModelListener(TicTacToeModelListener listener) {
            listeners.add(listener);
        }

        public void removeModelListener(TicTacToeModelListener listener) {
            listeners.remove(listener);
        }

        protected void fireGameWon() {
            for (TicTacToeModelListener listener : listeners) {
                listener.ticTacToeGameWon(this);
            }
        }

        public void checkRow() {

            if ((board[0] == Player.X || board[0] == Player.O) && (board[0] == board[1] && board[1] == board[2])) {
                winner = turn;
            }
            if ((board[3] == Player.X || board[3] == Player.O) && (board[3] == board[4] && board[4] == board[5])) {
                winner = turn;
            }
            if ((board[6] == Player.X || board[6] == Player.O) && (board[6] == board[7] && board[7] == board[8])) {
                winner = turn;
            }
        }

        public void checkDiagonal() {
            if ((board[0] == Player.X || board[0] == Player.O) && (board[0] == (board[4]) && board[4] == (board[8]))) {
                winner = turn;
            }
            if ((board[2] == Player.X || board[2] == Player.O) && (board[2] == (board[4]) && board[4] == (board[6]))) {
                winner = turn;
            }
        }

        public void checkColumn() {
            if ((board[0] == Player.X || board[0] == Player.O) && (board[0] == (board[3]) && board[3] == (board[6]))) {
                winner = turn;
            }
            if ((board[1] == Player.X || board[1] == Player.O) && (board[1] == (board[4]) && board[4] == (board[7]))) {
                winner = turn;
            }
            if ((board[2] == Player.X || board[2] == Player.O) && (board[2] == (board[5]) && board[5] == (board[8]))) {
                winner = turn;
            }
        }
    }

    public class TicTacToePane extends JPanel {

        private TicTacToeModel model;
        private GamePane gamePane;
        private WinPane winPane;

        public TicTacToePane() {
            CardLayout cardLayout = new CardLayout();

            model = new TicTacToeModel();
            model.addModelListener(new TicTacToeModelListener() {
                @Override
                public void ticTacToeGameWon(TicTacToeModel model) {
                    winPane.setWinner(model.getWinner());
                    cardLayout.show(TicTacToePane.this, "GameOverMan");
                }
            });

            winPane = new WinPane();
            gamePane = new GamePane(model);

            winPane.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (e.getActionCommand().equals(GameActions.PLAY_AGAIN.getCommand())) {
                        gamePane.reset();
                        cardLayout.show(TicTacToePane.this, "ReadyPlayer");
                    } else if (e.getActionCommand().equals(GameActions.STOP_PLAYING.getCommand())) {
                        SwingUtilities.windowForComponent(TicTacToePane.this).dispose();
                    }
                }
            });

            setLayout(cardLayout);
            add(winPane, "GameOverMan");
            add(gamePane, "ReadyPlayer");

            cardLayout.show(this, "ReadyPlayer");
            System.out.println("...");
        }

    }

    public class GamePane extends JPanel {

        private JButton board[];
        private TicTacToeModel model;

        public GamePane(TicTacToeModel model) {
            this.model = model;
            setLayout(new GridLayout(3, 3));
            board = new JButton[9];
            for (int row = 0; row < 3; row++) {
                for (int col = 0; col < 3; col++) {
                    int index = (row * 3) + col;
                    System.out.println(index);
                    board[index] = new JButton("-"); // Icon might be better
                    board[index].addActionListener(new ButtonActionListener(col, row));
                    add(board[index]);
                }
            }
            reset();
        }

        public void reset() {
            model.reset();
            for (int index = 0; index < board.length; index++) {
                board[index].setText("-");
            }
        }

        protected class ButtonActionListener implements ActionListener {

            private int col;
            private int row;

            public ButtonActionListener(int col, int row) {
                this.col = col;
                this.row = row;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                // Normally I'd use instanceof to check the source, but
                // I've deliberly limited the possible scope.
                JButton btn = (JButton) e.getSource();
                btn.setText(model.isX() ? "X" : "0");
                model.set(col, row);
                model.nextTurn();
            }

        }
    }

    public enum GameActions {
        PLAY_AGAIN("playAgain"), STOP_PLAYING("stopPlaying");

        private String command;

        private GameActions(String command) {
            this.command = command;
        }

        public String getCommand() {
            return command;
        }
    }

    public class WinPane extends JPanel {

        private JLabel winner;
        private JButton playAgain;
        private JButton end;

        public WinPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.insets = new Insets(8, 8, 8, 8);

            winner = new JLabel("");
            playAgain = new JButton("Play Again");
            playAgain.setActionCommand(GameActions.PLAY_AGAIN.getCommand());

            end = new JButton("Stop Playing");
            end.setActionCommand(GameActions.STOP_PLAYING.getCommand());

            add(new JLabel("Game Over!"), gbc);
            add(new JLabel("Player"), gbc);
            add(winner, gbc);
            add(new JLabel("Wins!"), gbc);

            JPanel buttons = new JPanel(new GridLayout(1, 0));
            buttons.add(playAgain);
            buttons.add(end);

            add(buttons, gbc);
        }

        public void setWinner(Player player) {
            if (player == Player.X) {
                winner.setText("X");
            } else if (player == Player.O) {
                winner.setText("0");
            } else {
                winner.setText("No boby knows");
            }
        }

        public void addActionListener(ActionListener listener) {
            playAgain.addActionListener(listener);
            end.addActionListener(listener);
        }

        public void removeActionListener(ActionListener listener) {
            playAgain.removeActionListener(listener);
            end.removeActionListener(listener);
        }

    }

}