0

当我尝试制作井字游戏时遇到问题。当我尝试使用 wait(); 时,会出现我遇到的问题;声明以暂停游戏,以便玩家能够查看谁赢得了游戏以及获胜方格是什么,但是当我尝试在这里运行这段代码时:

            wait(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

它在这里给了我这个错误代码:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at GameCode.restart(GameCode.java:264)
    at GameCode.xWins(GameCode.java:245)
    at GameCode.check(GameCode.java:171)
    at GameCode.actionPerformed(GameCode.java:70)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

它描述它是一个IllegalMonitorStateException,但是我尝试使用throw它来解决这个问题,但它仍然继续给我这个错误。有什么解决方案吗?如果您需要查看任何其他信息,请在此处参考我的代码:

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

public class GameCode implements ActionListener {
    
    Random random = new Random();
    JFrame frame = new JFrame();
    JPanel title_panel = new JPanel();
    JPanel button_panel = new JPanel();
    JLabel textfield = new JLabel();
    JButton[] buttons = new JButton[9];
    boolean player1_turn;
    
    
    
    
    GameCode() {
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500,500);
        frame.getContentPane().setBackground(new Color(0,0,0));
        frame.setLayout(new BorderLayout());
        frame.setVisible(true);
        
        textfield.setBackground(new Color(25,25,25));
        textfield.setForeground(new Color(25,255,0));
        textfield.setFont(new Font("TimesRoman", Font.BOLD,75));
        textfield.setHorizontalAlignment(JLabel.CENTER);
        textfield.setText("Tic Tac Toe");
        textfield.setOpaque(true);
        title_panel.setLayout(new BorderLayout());
        title_panel.setBounds(0,0,800,100);
        
        button_panel.setLayout(new GridLayout(3,3));
        button_panel.setBackground(new Color(150,25,25));
        
        for(int j = 0; j < 9; j++ ) {
            
            buttons[j] = new JButton();
            button_panel.add(buttons[j]);
            buttons[j].setFont(new Font("Ink Free", Font.BOLD,120));
            buttons[j].setFocusable(false);
            buttons[j].addActionListener(this);
            
        }
        
        
        title_panel.add(textfield);
        frame.add(title_panel, BorderLayout.NORTH);
        frame.add(button_panel);
        
        Turnone();
        
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        
        for (int i = 0; i < 9; i++) {
            
            if(arg0.getSource()==buttons[i]) {
                if(player1_turn) {
                    if(buttons[i].getText()=="") {
                        buttons[i].setForeground(new Color(255,0,0));
                        buttons[i].setText("X");
                        player1_turn=false;
                        textfield.setText("O turn");
                        check();
                    }
                } else {
                    if(buttons[i].getText()=="") {
                        buttons[i].setForeground(new Color(0,0,255));
                        buttons[i].setText("O");
                        player1_turn=true;
                        textfield.setText("X turn");
                        check();
                    }
                }
            }
        }
    }//Creating the Buttons the player will interact with
    
    public void Turnone() {
        
        for(int i=0; i<9;i++) {
            buttons[i].setEnabled(false);
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        for(int i=0; i<9;i++) {
            buttons[i].setEnabled(true);
        }
        
        if(random.nextInt(2)==0) {
            
            player1_turn = true;
            textfield.setText("X turn");
            
        } else {
            
            player1_turn = false;
            textfield.setText("O Turn");
            
        }
        
    }//Using a random int to decide which player will go first
    
    public void check() {
        //X Wins
        
        if(
                (buttons[0].getText()=="X") &&
                (buttons[1].getText()=="X") &&
                (buttons[2].getText()=="X") 
                ) {
            xWins(0,1,2);
        }
        if(
                (buttons[3].getText()=="X") &&
                (buttons[4].getText()=="X") &&
                (buttons[5].getText()=="X") 
                ) {
            xWins(3,4,5);
        }
        if(
                (buttons[6].getText()=="X") &&
                (buttons[7].getText()=="X") &&
                (buttons[8].getText()=="X") 
                ) {
            xWins(6,7,8);
        }
        if(
                (buttons[0].getText()=="X") &&
                (buttons[3].getText()=="X") &&
                (buttons[6].getText()=="X") 
                ) {
            xWins(0,3,6);
        }
        if(
                (buttons[1].getText()=="X") &&
                (buttons[4].getText()=="X") &&
                (buttons[7].getText()=="X") 
                ) {
            xWins(1,4,7);
        }
        if(
                (buttons[2].getText()=="X") &&
                (buttons[5].getText()=="X") &&
                (buttons[8].getText()=="X") 
                ) {
            xWins(2,5,8);
        }
        if(
                (buttons[0].getText()=="X") &&
                (buttons[4].getText()=="X") &&
                (buttons[8].getText()=="X") 
                ) {
            xWins(0,4,8);
        }
        if(
                (buttons[2].getText()=="X") &&
                (buttons[4].getText()=="X") &&
                (buttons[6].getText()=="X") 
                ) {
            xWins(2,4,6);
        }
        //O Wins
        
        if(
                (buttons[0].getText()=="O") &&
                (buttons[1].getText()=="O") &&
                (buttons[2].getText()=="O") 
                ) {
            oWins(0,1,2);
        }
        if(
                (buttons[3].getText()=="O") &&
                (buttons[4].getText()=="O") &&
                (buttons[5].getText()=="O") 
                ) {
            oWins(3,4,5);
        }
        if(
                (buttons[6].getText()=="O") &&
                (buttons[7].getText()=="O") &&
                (buttons[8].getText()=="O") 
                ) {
            oWins(6,7,8);
        }
        if(
                (buttons[0].getText()=="O") &&
                (buttons[3].getText()=="O") &&
                (buttons[6].getText()=="O") 
                ) {
            oWins(0,3,6);
        }
        if(
                (buttons[1].getText()=="O") &&
                (buttons[4].getText()=="O") &&
                (buttons[7].getText()=="O") 
                ) {
            oWins(1,4,7);
        }
        if(
                (buttons[2].getText()=="O") &&
                (buttons[5].getText()=="O") &&
                (buttons[8].getText()=="O") 
                ) {
            oWins(2,5,8);
        }
        if(
                (buttons[0].getText()=="O") &&
                (buttons[4].getText()=="O") &&
                (buttons[8].getText()=="O") 
                ) {
            oWins(0,4,8);
        }
        if(
                (buttons[2].getText()=="O") &&
                (buttons[4].getText()=="O") &&
                (buttons[6].getText()=="O") 
                ) {
            oWins(2,4,6);
        }
    
    }//Stating all the win conditions for the game
    
    public void xWins(int a, int b, int c) {
        buttons[a].setBackground(Color.GREEN);
        buttons[b].setBackground(Color.GREEN);
        buttons[c].setBackground(Color.GREEN);
        
        for(int i=0; i<9;i++) {
            buttons[i].setEnabled(false);
        }
        
        textfield.setText("X Wins!");
        
        restart();
    }//When Player X wins
    
    public void oWins(int a, int b, int c) {
        buttons[a].setBackground(Color.GREEN);
        buttons[b].setBackground(Color.GREEN);
        buttons[c].setBackground(Color.GREEN);
        
        for(int i=0; i<9;i++) {
            buttons[i].setEnabled(false);
        }
        textfield.setText("O Wins!");
        
        restart();
    }//When Player O wins 
    
    public void restart() { 
        
        try {
            wait(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        
    }
    
    
    
}//GameCode
4

2 回答 2

1

这是一个使用摇摆定时器的简单示例。

public void restart() { 
    Timer t = new Timer( 1000, evt->{
        //reset and enable the board.
        for(int i=0; i<9;i++) {
            buttons[i].setText("_");
            buttons[i].setEnabled(true);
        }
    }
    t.setRepeats(false);
    t.start();
}

这每次都会创建一个新计时器,并且不会跟踪它。因此,管理代码有明确的改进。希望它说明了一种安排摇摆事件的方法。

您收到等待代码的错误是因为您必须在对象上同步才能对其调用等待。您可以将您的等待调用替换为等待 + 同步以消除错误,但这不是一个好习惯,并且会在 EDT 等待时使您的 gui 无响应。

synchronize(this){
    wait(1000); 
}
于 2021-01-21T19:11:59.897 回答
0

您在事件线程上做的太多了,包括检查胜利和等待。因此,以下更改将在紧要关头起作用。

首先,将整个actionPerformed方法体放在一个单独的线程中。

    @Override
    public void actionPerformed(ActionEvent arg0) {
        new Thread(()-> {
        for (int i = 0; i < 9; i++) {
            
            if(arg0.getSource()==buttons[i]) {
                if(player1_turn) {
                    if(buttons[i].getText().equals("")) {
                        buttons[i].setForeground(new Color(255,0,0));
                        buttons[i].setText("X");
                        player1_turn=false;
                        textfield.setText("O turn");
                        check();
                    }
                } else {
                    if(buttons[i].getText().equals("")) {
                        buttons[i].setForeground(new Color(0,0,255));
                        buttons[i].setText("O");
                        player1_turn=true;
                        textfield.setText("X turn");
                        check();
                    }
                }
            }
        }
        }).start();
    }

然后在重启方法中使用睡眠是安全的。您也可以使用 Swing Timer,但不要在事件线程上进行过多处理仍然很重要。

public void restart() {
   try {
       Thread.sleep(2000);
   } catch (InterruptedException ie) {
   }
   System.out.println("Waking up");
  
}

但是在绘制和处理事件时,您的整体方法存在一些问题。您应该查看Java 教程以了解有关绘画和事件处理的更多信息。

于 2021-01-21T19:46:29.990 回答