Взаимодействие GUI и логики

Модернизировал игру ХО из книжки Файна, добавив минимакс-алгоритм и кнопку MOVE, которая заставляет программу делать ход первой (в авторской версии всегда начинает человек), и есть такая проблемка: если во время вычисления компьютером своего хода успеть пощёлкать по клеткам, то эти действия добавляются в EventQueue и затем сразу серией "выстреливают" на экране, а хотелось бы, чтобы игровое поле блокировалось до того момента, как программа сделает свой ход на доске. Подскажите, пожалуйста, в каком направлении копать: почитать дополнительно какие-то материалы непосредственно по SWING (если можно, чуть конретнее тему определить) или тут надо разбираться с многопоточностью в целом (notify, wait, семафоры и пр.)?

Класс GUI:

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

public class TTTJGUI implements ActionListener {
    
    private int emptySquaresLeft = 9;
    
    private JButton[] squares;
    private JButton newgame;
    private JButton move;
    private JLabel label;

    private JFrame frmTictactoe;

    public static void main(String[] args) {
         javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    TTTJGUI window = new TTTJGUI();
                    window.frmTictactoe.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private TTTJGUI() {
        initialize();
    }

    private void initialize() {
        
        frmTictactoe = new JFrame();
        frmTictactoe.setResizable(false);
        frmTictactoe.setSize(300, 400);
        frmTictactoe.setLocationRelativeTo(null);
        frmTictactoe.setTitle("TicTacToe");
        frmTictactoe.setFont(new Font("Monospaced", Font.BOLD, 20));
        frmTictactoe.setBackground(Color.CYAN);
        frmTictactoe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        JPanel panel = new JPanel();
        frmTictactoe.getContentPane().add(panel, BorderLayout.CENTER);
        panel.setLayout(new GridLayout(3, 3));
        
        squares = new JButton[9];
        for(int i=0; i<9; i++){
            squares[i] = new JButton(" ");
            squares[i].addActionListener(this);
            squares[i].setSize(100, 100);
            squares[i].setBackground(Color.ORANGE);
            squares[i].setFont(new Font("Monospaced", Font.BOLD, 50));
            panel.add(squares[i]);
        }
        
        JPanel panel_1 = new JPanel();
        panel_1.setBackground(Color.CYAN);
        frmTictactoe.getContentPane().add(panel_1, BorderLayout.NORTH);
        
        newgame = new JButton("New Game");
        newgame.addActionListener(this);
        newgame.setFont(new Font("Monospaced", Font.BOLD, 20));
        panel_1.add(newgame);
        
        move = new JButton("MOVE");
        move.addActionListener(this);
        move.setFont(new Font("Monospaced", Font.BOLD, 20));
        panel_1.add(move);
        
        JPanel panel_2 = new JPanel();
        frmTictactoe.getContentPane().add(panel_2, BorderLayout.SOUTH);
        
        label = new JLabel("Your turn!");
        panel_2.add(label);
        label.setFont(new Font("Monospaced", Font.BOLD, 25));
        label.setHorizontalAlignment(SwingConstants.CENTER);
    }

    public void actionPerformed(ActionEvent e) {

        JButton theButton = (JButton) e.getSource();
        String winner = " ";
        String board[];
        
        int spot = -1;
        
        if(theButton == newgame){
            move.setEnabled(true);
            for(int i=0; i<9; i++){
                squares[i].setEnabled(true);
                squares[i].setText(" ");
                squares[i].setBackground(Color.ORANGE);
            }
            emptySquaresLeft = 9;
            label.setText("Your turn!");
            return;
        }
        else if(theButton == move){
            move.setEnabled(false);
                board = new String[9];
                for(int i=0; i<9; i++){
                    board[i]=squares[i].getText();
                    }
                    AI.moveC(board, "O", 0, Integer.MIN_VALUE, Integer.MAX_VALUE);
                    spot = AI.best();
                    squares[spot].setText("O");
                    winner = lookForWinner();                   
                return;             
        }
        else
        for(int i=0; i<9; i++){
            if(theButton == squares[i] & squares[i].getText()==" "){
                move.setEnabled(false);
                squares[i].setText("X");
                winner = lookForWinner();
                if(!" ".equals(winner)){
                endTheGame();
                }
                else{                   
                    board = new String[9];
                    for(i=0; i<9; i++){
                        board[i]=squares[i].getText();
                    }
                    AI.moveC(board, "O", 0, Integer.MIN_VALUE, Integer.MAX_VALUE);
                    spot = AI.best();
                    squares[spot].setText("O");
                    winner = lookForWinner();
                    if (!" ".equals(winner)){
                    endTheGame();
                        }
                    }
                break;
            }
        }
        
        if(winner.equals("X")){
            label.setText("You win!!!");
            }
        else if(winner.equals("O")){
            label.setText("Comp wins!");
            }
        else if(winner.equals("T")){
            label.setText("It's a tie!");
            }
    }
    
    String lookForWinner() {
        
        emptySquaresLeft--;
        
        if (emptySquaresLeft==0){
            return "T";
            }
        else if((!squares[0].getText().equals(" ")&&squares[0].getText().equals(squares[1].getText())&&squares[0].getText().equals(squares[2].getText()))){
            highlightWinner(0, 1, 2, squares[0].getText());
            return squares[0].getText();
            }               
        else if((!squares[3].getText().equals(" ")&&squares[3].getText().equals(squares[4].getText())&&squares[3].getText().equals(squares[5].getText()))){
            highlightWinner(3, 4, 5, squares[3].getText());
            return squares[3].getText();
            }
        else if((!squares[6].getText().equals(" ")&&squares[6].getText().equals(squares[7].getText())&&squares[6].getText().equals(squares[8].getText()))){
            highlightWinner(6, 7, 8, squares[6].getText());
            return squares[6].getText();
            }
        else if((!squares[0].getText().equals(" ")&&squares[0].getText().equals(squares[3].getText())&&squares[0].getText().equals(squares[6].getText()))){
            highlightWinner(0, 3, 6, squares[0].getText());
            return squares[0].getText();
            }
        else if((!squares[1].getText().equals(" ")&&squares[1].getText().equals(squares[4].getText())&&squares[1].getText().equals(squares[7].getText()))){
            highlightWinner(1, 4, 7, squares[1].getText());
            return squares[1].getText();
            }
        else if((!squares[2].getText().equals(" ")&&squares[2].getText().equals(squares[5].getText())&&squares[2].getText().equals(squares[8].getText()))){
            highlightWinner(2, 5, 8, squares[2].getText());
            return squares[2].getText();
            }
        else if((!squares[0].getText().equals(" ")&&squares[0].getText().equals(squares[4].getText())&&squares[0].getText().equals(squares[8].getText()))){
            highlightWinner(0, 4, 8, squares[0].getText());
            return squares[0].getText();
            }
        else if((!squares[2].getText().equals(" ")&&squares[2].getText().equals(squares[4].getText())&&squares[2].getText().equals(squares[6].getText()))){
            highlightWinner(2, 4, 6, squares[2].getText());
            return squares[2].getText();
            }
        return " ";
    }
    
    void highlightWinner(int win1, int win2, int win3, String turn) {
        
        if(turn=="O"){
            squares[win1].setBackground(Color.RED);
            squares[win2].setBackground(Color.RED);
            squares[win3].setBackground(Color.RED);
        }
        else{
            squares[win1].setBackground(Color.GREEN);
            squares[win2].setBackground(Color.GREEN);
            squares[win3].setBackground(Color.GREEN);
        }
    }

    void endTheGame(){
        
        for(int i=0;i<9;i++){
        squares[i].setEnabled(false);
        }
    }
}

Класс логики:

import static java.lang.System.out;
import java.util.ArrayList;
import java.util.HashMap;

public class AI {
    
    static HashMap<Integer, Integer> scores = new HashMap<Integer, Integer>();
    
    static boolean endGameX(String[] virtual) {
        if  (virtual[0]==virtual[1]&&virtual[0]==virtual[2]&&virtual[0]=="X"){
            return true;        
            }
        else if (virtual[3]==virtual[4]&&virtual[3]==virtual[5]&&virtual[3]=="X"){
            return true;                
            }
        else if (virtual[6]==virtual[7]&&virtual[6]==virtual[8]&&virtual[6]=="X"){
            return true;                
            }
        else if (virtual[0]==virtual[3]&&virtual[0]==virtual[6]&&virtual[0]=="X"){              
            return true;
            }
        else if (virtual[1]==virtual[4]&&virtual[1]==virtual[7]&&virtual[1]=="X"){
            return true;                
            }
        else if (virtual[2]==virtual[5]&&virtual[2]==virtual[8]&&virtual[2]=="X"){
            return true;                
            }
        else if (virtual[0]==virtual[4]&&virtual[0]==virtual[8]&&virtual[0]=="X"){
            return true;                
            }
        else if (virtual[2]==virtual[4]&&virtual[2]==virtual[6]&&virtual[2]=="X"){
            return true;
            }
        return false;
    }
    
    static boolean endGameO(String[] virtual) {
        if  (virtual[0]==virtual[1]&&virtual[0]==virtual[2]&&virtual[0]=="O"){
            return true;        
            }
        else if (virtual[3]==virtual[4]&&virtual[3]==virtual[5]&&virtual[3]=="O"){
            return true;                
            }
        else if (virtual[6]==virtual[7]&&virtual[6]==virtual[8]&&virtual[6]=="O"){
            return true;                
            }
        else if (virtual[0]==virtual[3]&&virtual[0]==virtual[6]&&virtual[0]=="O"){              
            return true;
            }
        else if (virtual[1]==virtual[4]&&virtual[1]==virtual[7]&&virtual[1]=="O"){
            return true;                
            }
        else if (virtual[2]==virtual[5]&&virtual[2]==virtual[8]&&virtual[2]=="O"){
            return true;                
            }
        else if (virtual[0]==virtual[4]&&virtual[0]==virtual[8]&&virtual[0]=="O"){
            return true;                
            }
        else if (virtual[2]==virtual[4]&&virtual[2]==virtual[6]&&virtual[2]=="O"){
            return true;
            }
        return false;
    }

    static int minimax(ArrayList<Integer> moves, String turn, int alpha, int beta) {
        
        out.println(moves.size() + moves.toString() + " " + turn + " a=" + alpha + " b=" + beta);
        
    if(turn=="O"){
        for(int i=0; i<moves.size();i++){
            if (moves.get(i) > alpha){
                alpha = moves.get(i);
            }
            if(alpha >= beta){
            break;
            }
        }   
        return alpha;   
    }
    else{
        for (int i=0; i<moves.size();i++){
            if (moves.get(i) < beta){
                beta = moves.get(i);
            }
            if(alpha >= beta){
            break;
            }
        }   
        return beta;
    }
    }       

    static ArrayList<Integer> filter(String[] virtual) {
        
        ArrayList<Integer> empty = new ArrayList<>();
        for(int i=0; i<virtual.length; i++) {
            if(virtual[i]==" ") {
                empty.add(i);
                if(virtual[i]!=" ") {
                    empty.remove(i);
                }
            }
        }
        return empty;
    }
    
    static int moveC(String[] virtual, String turn, int depth, int alpha, int beta) {

        ArrayList<Integer> empty = new ArrayList<Integer>();
        empty = filter(virtual);

        if(endGameO(virtual)){
            return 10+depth;
        }
        if(endGameX(virtual)){
            return -(10+depth); 
        }           
        if(empty.size()==0) {
            return 0;
        }       
        
        ArrayList<Integer> moves = new ArrayList<>();
        
        for (int i=0; i<empty.size(); i++) {
            int spot = empty.get(i);                        
            if(turn=="O"){
                virtual[empty.get(i)] = "O";
                int value = moveC(virtual, "X", depth-1, alpha, beta);
                if(value > alpha){
                    alpha = value;
                    moves.add(value);
                    }
            if(depth==0){
                scores.put(spot, value);
                }
            }
            else{
                virtual[empty.get(i)] = "X";
                int value = moveC(virtual, "O", depth-1, alpha, beta);
                if(value < beta){
                    beta = value;
                    moves.add(value);
                    }
                }
            virtual[empty.get(i)] = " ";
            if(alpha >= beta){
                break;
            }
        }       
    return minimax(moves, turn, alpha, beta);
}
    
    static int best() {
        
        out.println(scores.size() + scores.toString() + " scores");
        
        int value = -999;
        int seed = -1;
    
        for(HashMap.Entry<Integer, Integer> entry: scores.entrySet()) {
            if(value < entry.getValue()){
                value = entry.getValue();
                seed = entry.getKey();
            }           
        }
        scores.clear();
        return seed;
    }

}


Ответы (0 шт):