Java swing睡眠命令

Java swing睡眠命令,java,swing,Java,Swing,我正在用人工智能创建一个棋盘游戏,我试图让人工智能选择放置游戏块的方块闪烁一两秒钟,然后再进行所选的移动。我的尝试如下: 线程。睡眠 button.setBackground(Color.pink); Thread.sleep(800); button.setBackground((new JButton()).getBackground()); Thread.sleep(800); button.setBackground(Color.pink); Thread.sleep(800); but

我正在用人工智能创建一个棋盘游戏,我试图让人工智能选择放置游戏块的方块闪烁一两秒钟,然后再进行所选的移动。我的尝试如下:

线程。睡眠

button.setBackground(Color.pink);
Thread.sleep(800);
button.setBackground((new JButton()).getBackground());
Thread.sleep(800);
button.setBackground(Color.pink);
Thread.sleep(800);
button.setBackground((new JButton()).getBackground());
Thread.sleep(800);
线程

Thread flash = new Thread(new ButtonFlashThread(button));
flash.start();
可调用

ExecutorService es = Executors.newSingleThreadExecutor();
    Future<Boolean> task = es.submit(new ButtonFlashThread(button));
计时器

Runnable flashON = new Runnable() {
         public void run() { button.setBackground(Color.pink); } };
     Runnable flashOFF = new Runnable() {
         public void run() { button.setBackground((new JButton()).getBackground()); } };
         javax.swing.SwingUtilities.invokeLater(flashON);
         javax.swing.SwingUtilities.invokeLater(flashOFF);
         javax.swing.SwingUtilities.invokeLater(flashON);
         javax.swing.SwingUtilities.invokeLater(flashOFF);
    ActionListener flashON = new ActionListener(){
        public void actionPerformed(ActionEvent arg0){ button.setBackground(Color.pink); } };
    ActionListener flashOFF = new ActionListener(){
        public void actionPerformed(ActionEvent arg0) { button.setBackground((new JButton()).getBackground()); } };

    int sleep = 800;
    Timer timer = new Timer(sleep, flashON); timer.setRepeats(false); timer.start();
    timer = new Timer(sleep, flashOFF); timer.setRepeats(false); timer.start();
    timer = new Timer(sleep, flashON); timer.setRepeats(false); timer.start();
    timer = new Timer(sleep, flashOFF); timer.setRepeats(false); timer.start();
Sleep命令冻结GUI,当按钮闪烁时,所有其他尝试都会继续执行代码。不是我想要的那样。我希望按钮闪烁,代码暂停,直到按钮闪烁完毕,然后才恢复。基本上,我正在寻找一种方法来完成以下工作:

//Find desired move (done)
//Flash the JButton a few times to indicate selected move
//Do following move (done)
正是按照这个顺序

编辑1: 下面的实现

private void flashButton(JButton button) {      
    class MoveTimerListener implements ActionListener {
        private boolean flashOn = false;
        private int count;
        private int MAX_COUNT = 5;
        private JButton button;

        public MoveTimerListener(JButton b) {
            button = b;
        }

        public void actionPerformed(ActionEvent e) {
            flashOn = !flashOn;
            if (count >= MAX_COUNT) { // MAX_COUNT is an int constant
                // reached max -- stop timer
                ((Timer) e.getSource()).stop();
                flashOn = false;

                aiMove();
                updateGUI();
            }

            if (flashOn)
                button.setBackground(Color.yellow);
            else
                button.setBackground((new JButton()).getBackground());
            count++;
        }
    }

    Timer t = new Timer(5000, new MoveTimerListener(button));
    t.start();
    updateGUI();
}
在代码完成很久之后,当按钮仍在后台闪烁时,不要暂停代码并让其继续

编辑2: 我实现了您的示例,如下所示:

private void flashButton() {        
    _moveTimer = new Timer(100, new MoveTimerListener());
    _moveTimer.start();
    updateGUI();
}

private class MoveTimerListener implements ActionListener {
    private boolean flashOn = false;
    private int count;

    @Override
    public void actionPerformed(ActionEvent e) {
        flashOn = !flashOn;
        if (count >= 20) {
            ((Timer) e.getSource()).stop();
            flashOn = false;
            _gm.makeMove(aiMove[0], aiMove[1]);
        }

        if (flashOn) {
            _boardButtons[aiMove[0]][aiMove[1]].setBackground(Color.yellow);
        } else {
            _boardButtons[aiMove[0]][aiMove[1]].setBackground((new JButton()).getBackground());
        }
        count++;
    }
}
然而,代码似乎总是跳过actionPerformed方法。我做错什么了吗

编辑3:不是很小,但可以运行的程序。有问题的代码在第95-140行

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.LinkedList;
import java.util.Random;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

public class GameGUI extends JFrame implements MouseListener {

private GameManager _gm;

private JLabel[] _scores;
private JLabel[] _players;
private JPanel _contentPane;
private JButton[] _toolbarButtons;
private JButton[][] _boardButtons;
private Timer _moveTimer;
private int[] aiMove;


public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                GameManager gm = new GameManager();
                //gm.addPlayer(new Player("player", 2, 0));
                gm.addPlayer(new Player("random", 2, 1));
                gm.addPlayer(new Player("max kills ai", 1, 2));
                gm.initBoard(8, 8);
                GameGUI frame = new GameGUI(gm);
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */
public GameGUI(GameManager gm) {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    _contentPane = new JPanel();
    _boardButtons = new JButton[gm.getBoardSize()[0]][gm.getBoardSize()[1]];
    _gm = gm;
    addWindowGUI(_contentPane);
    setContentPane(_contentPane);
    aiMove();
    updateGUI();
}

private void addWindowGUI(JPanel cp) {
    cp.setLayout(new BoxLayout(_contentPane, BoxLayout.PAGE_AXIS));

    JPanel gameInfo = new JPanel();
    gameInfo.setLayout(new FlowLayout());

    //Game grid
    JPanel gameGrid = new JPanel();
    int buttonSize = 40;
    gameGrid.setLayout(new GridLayout(_gm.getBoardSize()[0], _gm.getBoardSize()[1]));
    for (int i = 0; i < _boardButtons.length; i++)
        for (int j = 0; j < _boardButtons[i].length; j++) {
            _boardButtons[i][j] = new JButton();
            _boardButtons[i][j].setPreferredSize(new Dimension(buttonSize, buttonSize));
            _boardButtons[i][j].addMouseListener(this);
            gameGrid.add(_boardButtons[i][j]);
        }
    gameInfo.add(gameGrid);
    cp.add(gameInfo);
}

public void mouseClicked(MouseEvent e) {
    if (!_gm.getCurrentPlayer().isAI()) {
        //Find desired move and conduct it
        for (int i = 0; i < _boardButtons.length; i++)
            for (int j = 0; j < _boardButtons[i].length; j++)
                if (e.getSource().equals(_boardButtons[i][j]))
                    _gm.makeMove(i,j);

        aiMove();
        updateGUI();
    }
}

public void aiMove() {
    int winner = _gm.isGameOver();
    while (winner == -1 && _gm.getCurrentPlayer().getAI() != 0) {
        updateGUI();
        aiMove = _gm.getNextAIMove();
        flashButton();
        winner = _gm.isGameOver();
    }

    if (winner != -1) {
        // Winner
    }
}

private void flashButton() {        
    _moveTimer = new Timer(100, new MoveTimerListener());
    _moveTimer.start();
    updateGUI();
}

private class MoveTimerListener implements ActionListener {
    private boolean flashOn = false;
    private int count;

    @Override
    public void actionPerformed(ActionEvent e) {
        flashOn = !flashOn;
        if (count >= 20) {
            ((Timer) e.getSource()).stop();
            flashOn = false;
            _gm.makeMove(aiMove[0], aiMove[1]);
        }

        if (flashOn) {
            _boardButtons[aiMove[0]][aiMove[1]].setBackground(Color.yellow);
        } else {
            _boardButtons[aiMove[0]][aiMove[1]].setBackground((new JButton()).getBackground());
        }
        count++;
    }
}

public void mouseEntered(MouseEvent e) {
    if (!_gm.getCurrentPlayer().isAI()) {
        LinkedList<int[]> l = new LinkedList<int[]>();
        for (int i = 0; i < _boardButtons.length; i++)
            for (int j = 0; j < _boardButtons[i].length; j++)
                if (e.getSource().equals(_boardButtons[i][j]))
                    l = _gm.canPlace(i,j);
        for (int i = 0; i < l.size(); i++) {
            int[] temp = l.get(i);
            _boardButtons[temp[0]][temp[1]].setBackground(Color.yellow);
        }
    }
}
private void updateGUI() {
    for (int i = 0; i < _boardButtons.length; i++)
        for (int j = 0; j < _boardButtons[i].length; j++)
            if (_gm.getBoard().stoneAt(i, j) == 1)
                _boardButtons[i][j].setBackground(Color.green);
            else if (_gm.getBoard().stoneAt(i, j) == 2)
                _boardButtons[i][j].setBackground(Color.red);
}
public void mouseExited(MouseEvent arg0) { updateGUI(); }

//Not relevant
public void mousePressed(MouseEvent arg0) { }
public void mouseReleased(MouseEvent arg0) { }


//Other classes
public static class GameManager {
    private int _turn;
    private Player[] _players;
    private GameBoard _board;
    private GameLog _log;

    public int getTurn() { return _turn; }
    public Player[] getPlayers() { return _players; }
    public GameBoard getBoard() { return _board; }

    public GameManager() {
        _turn = 0;
        _players = new Player[0];
    }

    public int[] getNextAIMove() {
        AI ai = new AI();
        return ai.play(_players[_turn].getAI(), _board, _players[_turn].getColour());
    }

    public void initBoard(int m, int n) {
        int[] colours = new int[_players.length];
        for (int i = 0; i < colours.length; i++)
            colours[i] = _players[i].getColour();
        _board = new GameBoard(m, n, colours);
        updateScore();
    }

    public void addPlayer(Player p) {
        Player[] temp = _players;
        _players = new Player[temp.length + 1];
        for (int i = 0; i < temp.length; i++)
            _players[i] = temp[i];
        _players[temp.length] = new Player(p);

        Random rnd = new Random();
        _turn = rnd.nextInt(_players.length);
    }

    private void advanceTurn() {
        _turn++;
        if(_turn == _players.length) 
            _turn = 0;
    }

    public void makeMove(int y, int x) {
        if (_board.place(y, x, _players[_turn].getColour()) != 0) {
            updateScore();
            advanceTurn();
        }
    }

    public LinkedList<int[]> canPlace(int y, int x) {
        return _board.canPlace(y, x, _players[_turn].getColour());
    }

    public int[] getBoardSize() {
        return _board.getSize();
    }

    private void updateScore() {
        int[] scores = new int[_players.length];
        for (int i = 0; i < _board.getSize()[0]; i++)
            for (int j = 0; j < _board.getSize()[1]; j++)
                for (int j2 = 0; j2 < _players.length; j2++)
                    if (_players[j2].getColour() == _board.stoneAt(i, j))
                        scores[j2]++;
        for (int i = 0; i < _players.length; i++) {
            _players[i].setScore(scores[i]);
        }
    }

    public int isGameOver() {
        int winner = 0;
        for (int i = 0; i < _players.length; i++) {
            for (int j = 0; j < _board.getSize()[0]; j++)
                for (int j2 = 0; j2 < _board.getSize()[1]; j2++)
                    if (canPlace(j, j2).size() != 0)
                        return -1;
            advanceTurn();
        }
        for (int i = 1; i < _players.length; i++)
            if (_players[i].getPoints() > _players[winner].getPoints())
                winner = i;
        return winner;
    }
    public Player getCurrentPlayer() {
        return _players[_turn];
    }
}

public static class AI {
    public int[] play(int diff, GameBoard board, int colour) {
        //List all possible moves
        int[] move = new int[2];
        LinkedList<int[]> posibilities = new LinkedList<int[]>();
        for (int i = 0; i < board.getSize()[0]; i++)
            for (int j = 0; j < board.getSize()[1]; j++)
                if (board.canPlace(i, j, colour).size() > 0) {
                    int[] temp = {i, j};
                    posibilities.add(temp);
                }

        //Choose a move according to AI difficulty
        switch (diff) {
        case 1: // Easy - random
            Random r = new Random();
            move = posibilities.get(r.nextInt(posibilities.size()));
            break;

        case 2: // Medium - max kills
            int max = 0, kills = board.canPlace(posibilities.get(0)[0], posibilities.get(0)[1], colour).size();
            for (int i = 1; i < posibilities.size(); i++) {
                int[] temp = posibilities.get(i);
                int tempkills = board.canPlace(temp[0], temp[1], colour).size();
                if (kills < tempkills) {
                    kills = tempkills;
                    max = i;
                }
            }
            move = posibilities.get(max);
            break;

        case 3: // Hard
            break;
        }

        return move;
    }
}

public static class GameBoard {
    private int[][] _board;
    private int _m;
    private int _n;

    public GameBoard(int m, int n, int[] colours) {
        _m = m;
        _n = n;
        _board = new int[m][n];
        for (int i = 0; i < _board.length; i++)
            for (int j = 0; j < _board[i].length; j++)
                _board[i][j] = 0;
        if (_m % 2 == 0 && _n % 2 == 0) {
            _board[m/2][n/2] = _board[m/2 - 1][n/2 - 1] = colours[0];
            _board[m/2][n/2 - 1] = _board[m/2 - 1][n/2] = colours[1];
        }

        int[][] testBoard = {
                {2, 2, 2, 2, 1, 1, 2, 2},
                {2, 1, 2, 2, 1, 1, 1, 2},
                {1, 1, 2, 2, 1, 2, 2, 1},
                {2, 2, 2, 1, 2, 1, 1, 1},
                {2, 2, 1, 2, 1, 1, 1, 2},
                {1, 1, 1, 2, 2, 2, 2, 2},
                {1, 1, 1, 2, 2, 2, 2, 2},
                {1, 1, 1, 2, 1, 1, 1, 0}};
        //_board = testBoard;
    }

    public int[] getSize() {
        int[] size = {_m, _n};
        return size;
    }

    public LinkedList<int[]> canPlace(int y, int x, int colour) {
        LinkedList<int[]> eats = new LinkedList<int[]>();
        if (_board[y][x] != 0) return eats;
        int i;
        if (existsAnotherIn("u", y, x, colour)) {
            i = 1;
            while (isInBounds(y + i, x) && _board[y + i][x] != colour && _board[y + i][x] != 0) {
                int[] temp = {y + i, x};
                eats.add(temp);
                i++;
            }
        }
        if (existsAnotherIn("d", y, x, colour)) {
            i = 1;
            while (isInBounds(y - i, x) && _board[y - i][x] != colour && _board[y - i][x] != 0) {
                int[] temp = {y - i, x};
                eats.add(temp);
                i++;
            }       
        }
        if (existsAnotherIn("l", y, x, colour)) {
            i = 1;
            while (isInBounds(y, x - i) && _board[y][x - i] != colour && _board[y][x - i] != 0) {
                int[] temp = {y, x - i};
                eats.add(temp);
                i++;
            }
        }
        if (existsAnotherIn("r", y, x, colour)) {
            i = 1;
            while (isInBounds(y, x + i) && _board[y][x + i] != colour && _board[y][x + i] != 0) {
                int[] temp = {y, x + i};
                eats.add(temp);
                i++;
            }
        }
        if (existsAnotherIn("ul", y, x, colour)) {
            i = 1;
            while (isInBounds(y + i, x - i) && _board[y + i][x - i] != colour && _board[y + i][x - i] != 0) {
                int[] temp = {y + i, x - i};
                eats.add(temp);
                i++;
            }
        }
        if (existsAnotherIn("ur", y, x, colour)) {
            i = 1;
            while (isInBounds(y + i, x + i) && _board[y + i][x + i] != colour && _board[y + i][x + i] != 0) {
                int[] temp = {y + i, x + i};
                eats.add(temp);
                i++;
            }
        }
        if (existsAnotherIn("dl", y, x, colour)) {
            i = 1;
            while (isInBounds(y - i, x - i) && _board[y - i][x - i] != colour && _board[y - i][x - i] != 0) {
                int[] temp = {y - i, x - i};
                eats.add(temp);
                i++;
            }
        }
        if (existsAnotherIn("dr", y, x, colour)) {
            i = 1;
            while (isInBounds(y - i, x + i) && _board[y - i][x + i] != colour && _board[y - i][x + i] != 0) {
                int[] temp = {y - i, x + i};
                eats.add(temp);
                i++;
            }
        }
        return eats;
    }

    private boolean isInBounds(int i, int j) {
        return i >= 0 && j >= 0 && i < _m && j < _n;
    }

    private boolean existsAnotherIn(String lane, int vo, int ho, int colour) {
        int v = 0, h = 0;

        do {
            if ((v != 0 || h != 0) && _board[vo + v][ho + h] == colour) return true;

            if (lane.contains("u"))         v++;
            else if (lane.contains("d"))    v--;
            if (lane.contains("r"))         h++;
            else if (lane.contains("l"))    h--;
        } while (isInBounds(vo + v, ho + h) && _board[vo + v][ho + h] != 0);
        return false;
    }

    public int place(int y, int x, int colour) {
        LinkedList<int[]> stonesToEat = canPlace(y, x, colour);
        if (!stonesToEat.isEmpty()) {
            _board[y][x] = colour;
            for (int i = 0; i < stonesToEat.size(); i++) {
                int[] place = stonesToEat.get(i);
                _board[place[0]][place[1]] = colour;
            }
        }
        return stonesToEat.size();
    }

    public String toString() {
        String s = "";
        for (int i = 0; i < _board.length; i++) {
            for (int j = 0; j < _board[0].length; j++) {
                s+=_board[i][j]+"\t";
            }
            s += "\n";
        }
        return s;
    }

    public int stoneAt(int i, int j) {
        return _board[i][j];
    }
}

public static class Player {
    private String _name;
    private int _points;
    private int _colour;
    private int _ai;

    public Player(String name, int colour, int ai) {
        _name = name;
        _points = 0;
        _colour = colour;
        _ai = ai;
    }

    public void setScore(int s) {
        _points = s;
    }

    public Player(Player p) {
        _name = p._name;
        _points = p._points;
        _colour = p._colour;
        _ai = p._ai;
    }

    public boolean isAI() {
        return _ai != 0;
    }

    public void addPoints(int add) { _points += add; }

    public int getColour() { return _colour; }

    public String getName() { return _name; }

    public int getPoints() { return _points; }

    public int getAI() { return _ai; }
}

public class GameLog extends GameManager {
    private int _startingPlayer;
    private LinkedList<String> _moves;

    public GameLog(int startPlayer) {
        _startingPlayer = startPlayer;
        _moves = new LinkedList<String>();
    }

    public void addMove(String m) {
        _moves.add(m);
    }

    public int getStartingPlayer() { return _startingPlayer; }

    public LinkedList<String> getMoves() { return _moves; }
}
import java.awt.*;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseListener;
导入java.util.LinkedList;
导入java.util.Random;
导入javax.swing.BoxLayout;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
导入javax.swing.Timer;
公共类GameGUI扩展JFrame实现MouseListener{
私人游戏经理(总经理);
私人JLabel[]_分数;
私人JLabel[]_玩家;
私有JPanel_内容窗格;
私有JButton[]\u工具栏按钮;
专用JButton[][]按钮;
私人定时器(moveTimer),;
私人国际[]爱慕;
公共静态void main(字符串[]args){
invokeLater(新的Runnable(){
公开募捐{
试一试{
GameManager gm=新GameManager();
//gm.addPlayer(新玩家(“玩家”,2,0));
gm.addPlayer(新玩家(“随机”,2,1));
gm.addPlayer(新玩家(“max杀死ai”,1,2));
董事会总经理(8,8);
GameGUI框架=新GameGUI(gm);
frame.setVisible(true);
}捕获(例外e){
e、 printStackTrace();
}
}
});
}
/**
*创建框架。
*/
公共游戏GUI(游戏管理器总经理){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
立根(100100450300);
_contentPane=newjpanel();
_boardButtons=新的JButton[gm.getBoardSize()[0]][gm.getBoardSize()[1]];
_gm=gm;
addWindowGUI(_contentPane);
setContentPane(_contentPane);
aiMove();
updateGUI();
}
私有void addWindowGUI(JPanel cp){
cp.setLayout(新的BoxLayout(_contentPane,BoxLayout.PAGE_AXIS));
JPanel gameInfo=新的JPanel();
gameInfo.setLayout(新的FlowLayout());
//游戏网格
JPanel gameGrid=新的JPanel();
int按钮大小=40;
gameGrid.setLayout(新的GridLayout(_gm.getBoardSize()[0],_gm.getBoardSize()[1]);
对于(int i=0;i<\u boardButtons.length;i++)
对于(int j=0;j<_boardButtons[i]。长度;j++){
_boardButtons[i][j]=新的JButton();
_boardButtons[i][j].setPreferredSize(新尺寸(buttonSize,buttonSize));
_boardButtons[i][j].addMouseListener(本);
gameGrid.add(_boardButtons[i][j]);
}
gameInfo.add(gameGrid);
cp.add(gameInfo);
}
公共无效mouseClicked(MouseEvent e){
如果(!\u gm.getCurrentPlayer().isAI()){
//找到想要的动作并进行
对于(int i=0;i<\u boardButtons.length;i++)
对于(int j=0;j<_boardButtons[i]。长度;j++)
如果(e.getSource().equals(_[i][j]))
_总经理马克莫夫(i,j);
aiMove();
updateGUI();
}
}
公共无效aiMove(){
int winner=_gm.isGameOver();
while(winner==-1&&u gm.getCurrentPlayer().getAI()!=0){
updateGUI();
aiMove=_gm.getNextAIMove();
flashButton();
获胜者=_gm.isGameOver();
}
如果(获胜者!=-1){
//胜利者
}
}
私有void flashButton(){
_moveTimer=新计时器(100,新的MoveTimerListener());
_moveTimer.start();
updateGUI();
}
私有类MoveTimerListener实现ActionListener{
私有布尔flashOn=false;
私人整数计数;
@凌驾
已执行的公共无效操作(操作事件e){
闪光=!闪光;
如果(计数>=20){
((计时器)e.getSource()).stop();
闪光=假;
_gm.makeMove(aiMove[0],aiMove[1]);
}
如果(闪络){
_boardButtons[aiMove[0]][aiMove[1]].背景(颜色.黄色);
}否则{
_boardButtons[aiMove[0]][aiMove[1]].setBackground((新的JButton()).getBackground());
}
计数++;
}
}
公共无效鼠标事件(鼠标事件e){
如果(!\u gm.getCurrentPlayer().isAI()){
LinkedList l=新建LinkedList();
对于(int i=0;i<\u boardButtons.length;i++)
对于(int j=0;j<_boardButtons[i]。长度;j++)
如果(e.getSource().equals(_[i][j]))
l=_gm.canPlace(i,j);
对于(int i=0;iimport java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.LinkedList;
import java.util.Random;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

public class GameGUI extends JFrame implements MouseListener {

private GameManager _gm;

private JLabel[] _scores;
private JLabel[] _players;
private JPanel _contentPane;
private JButton[] _toolbarButtons;
private JButton[][] _boardButtons;
private Timer _moveTimer;
private int[] aiMove;


public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                GameManager gm = new GameManager();
                //gm.addPlayer(new Player("player", 2, 0));
                gm.addPlayer(new Player("random", 2, 1));
                gm.addPlayer(new Player("max kills ai", 1, 2));
                gm.initBoard(8, 8);
                GameGUI frame = new GameGUI(gm);
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */
public GameGUI(GameManager gm) {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    _contentPane = new JPanel();
    _boardButtons = new JButton[gm.getBoardSize()[0]][gm.getBoardSize()[1]];
    _gm = gm;
    addWindowGUI(_contentPane);
    setContentPane(_contentPane);
    aiMove();
    updateGUI();
}

private void addWindowGUI(JPanel cp) {
    cp.setLayout(new BoxLayout(_contentPane, BoxLayout.PAGE_AXIS));

    JPanel gameInfo = new JPanel();
    gameInfo.setLayout(new FlowLayout());

    //Game grid
    JPanel gameGrid = new JPanel();
    int buttonSize = 40;
    gameGrid.setLayout(new GridLayout(_gm.getBoardSize()[0], _gm.getBoardSize()[1]));
    for (int i = 0; i < _boardButtons.length; i++)
        for (int j = 0; j < _boardButtons[i].length; j++) {
            _boardButtons[i][j] = new JButton();
            _boardButtons[i][j].setPreferredSize(new Dimension(buttonSize, buttonSize));
            _boardButtons[i][j].addMouseListener(this);
            gameGrid.add(_boardButtons[i][j]);
        }
    gameInfo.add(gameGrid);
    cp.add(gameInfo);
}

public void mouseClicked(MouseEvent e) {
    if (!_gm.getCurrentPlayer().isAI()) {
        //Find desired move and conduct it
        for (int i = 0; i < _boardButtons.length; i++)
            for (int j = 0; j < _boardButtons[i].length; j++)
                if (e.getSource().equals(_boardButtons[i][j]))
                    _gm.makeMove(i,j);

        aiMove();
        updateGUI();
    }
}

public void aiMove() {
    int winner = _gm.isGameOver();
    while (winner == -1 && _gm.getCurrentPlayer().getAI() != 0) {
        updateGUI();
        aiMove = _gm.getNextAIMove();
        flashButton();
        winner = _gm.isGameOver();
    }

    if (winner != -1) {
        // Winner
    }
}

private void flashButton() {        
    _moveTimer = new Timer(100, new MoveTimerListener());
    _moveTimer.start();
    updateGUI();
}

private class MoveTimerListener implements ActionListener {
    private boolean flashOn = false;
    private int count;

    @Override
    public void actionPerformed(ActionEvent e) {
        flashOn = !flashOn;
        if (count >= 20) {
            ((Timer) e.getSource()).stop();
            flashOn = false;
            _gm.makeMove(aiMove[0], aiMove[1]);
        }

        if (flashOn) {
            _boardButtons[aiMove[0]][aiMove[1]].setBackground(Color.yellow);
        } else {
            _boardButtons[aiMove[0]][aiMove[1]].setBackground((new JButton()).getBackground());
        }
        count++;
    }
}

public void mouseEntered(MouseEvent e) {
    if (!_gm.getCurrentPlayer().isAI()) {
        LinkedList<int[]> l = new LinkedList<int[]>();
        for (int i = 0; i < _boardButtons.length; i++)
            for (int j = 0; j < _boardButtons[i].length; j++)
                if (e.getSource().equals(_boardButtons[i][j]))
                    l = _gm.canPlace(i,j);
        for (int i = 0; i < l.size(); i++) {
            int[] temp = l.get(i);
            _boardButtons[temp[0]][temp[1]].setBackground(Color.yellow);
        }
    }
}
private void updateGUI() {
    for (int i = 0; i < _boardButtons.length; i++)
        for (int j = 0; j < _boardButtons[i].length; j++)
            if (_gm.getBoard().stoneAt(i, j) == 1)
                _boardButtons[i][j].setBackground(Color.green);
            else if (_gm.getBoard().stoneAt(i, j) == 2)
                _boardButtons[i][j].setBackground(Color.red);
}
public void mouseExited(MouseEvent arg0) { updateGUI(); }

//Not relevant
public void mousePressed(MouseEvent arg0) { }
public void mouseReleased(MouseEvent arg0) { }


//Other classes
public static class GameManager {
    private int _turn;
    private Player[] _players;
    private GameBoard _board;
    private GameLog _log;

    public int getTurn() { return _turn; }
    public Player[] getPlayers() { return _players; }
    public GameBoard getBoard() { return _board; }

    public GameManager() {
        _turn = 0;
        _players = new Player[0];
    }

    public int[] getNextAIMove() {
        AI ai = new AI();
        return ai.play(_players[_turn].getAI(), _board, _players[_turn].getColour());
    }

    public void initBoard(int m, int n) {
        int[] colours = new int[_players.length];
        for (int i = 0; i < colours.length; i++)
            colours[i] = _players[i].getColour();
        _board = new GameBoard(m, n, colours);
        updateScore();
    }

    public void addPlayer(Player p) {
        Player[] temp = _players;
        _players = new Player[temp.length + 1];
        for (int i = 0; i < temp.length; i++)
            _players[i] = temp[i];
        _players[temp.length] = new Player(p);

        Random rnd = new Random();
        _turn = rnd.nextInt(_players.length);
    }

    private void advanceTurn() {
        _turn++;
        if(_turn == _players.length) 
            _turn = 0;
    }

    public void makeMove(int y, int x) {
        if (_board.place(y, x, _players[_turn].getColour()) != 0) {
            updateScore();
            advanceTurn();
        }
    }

    public LinkedList<int[]> canPlace(int y, int x) {
        return _board.canPlace(y, x, _players[_turn].getColour());
    }

    public int[] getBoardSize() {
        return _board.getSize();
    }

    private void updateScore() {
        int[] scores = new int[_players.length];
        for (int i = 0; i < _board.getSize()[0]; i++)
            for (int j = 0; j < _board.getSize()[1]; j++)
                for (int j2 = 0; j2 < _players.length; j2++)
                    if (_players[j2].getColour() == _board.stoneAt(i, j))
                        scores[j2]++;
        for (int i = 0; i < _players.length; i++) {
            _players[i].setScore(scores[i]);
        }
    }

    public int isGameOver() {
        int winner = 0;
        for (int i = 0; i < _players.length; i++) {
            for (int j = 0; j < _board.getSize()[0]; j++)
                for (int j2 = 0; j2 < _board.getSize()[1]; j2++)
                    if (canPlace(j, j2).size() != 0)
                        return -1;
            advanceTurn();
        }
        for (int i = 1; i < _players.length; i++)
            if (_players[i].getPoints() > _players[winner].getPoints())
                winner = i;
        return winner;
    }
    public Player getCurrentPlayer() {
        return _players[_turn];
    }
}

public static class AI {
    public int[] play(int diff, GameBoard board, int colour) {
        //List all possible moves
        int[] move = new int[2];
        LinkedList<int[]> posibilities = new LinkedList<int[]>();
        for (int i = 0; i < board.getSize()[0]; i++)
            for (int j = 0; j < board.getSize()[1]; j++)
                if (board.canPlace(i, j, colour).size() > 0) {
                    int[] temp = {i, j};
                    posibilities.add(temp);
                }

        //Choose a move according to AI difficulty
        switch (diff) {
        case 1: // Easy - random
            Random r = new Random();
            move = posibilities.get(r.nextInt(posibilities.size()));
            break;

        case 2: // Medium - max kills
            int max = 0, kills = board.canPlace(posibilities.get(0)[0], posibilities.get(0)[1], colour).size();
            for (int i = 1; i < posibilities.size(); i++) {
                int[] temp = posibilities.get(i);
                int tempkills = board.canPlace(temp[0], temp[1], colour).size();
                if (kills < tempkills) {
                    kills = tempkills;
                    max = i;
                }
            }
            move = posibilities.get(max);
            break;

        case 3: // Hard
            break;
        }

        return move;
    }
}

public static class GameBoard {
    private int[][] _board;
    private int _m;
    private int _n;

    public GameBoard(int m, int n, int[] colours) {
        _m = m;
        _n = n;
        _board = new int[m][n];
        for (int i = 0; i < _board.length; i++)
            for (int j = 0; j < _board[i].length; j++)
                _board[i][j] = 0;
        if (_m % 2 == 0 && _n % 2 == 0) {
            _board[m/2][n/2] = _board[m/2 - 1][n/2 - 1] = colours[0];
            _board[m/2][n/2 - 1] = _board[m/2 - 1][n/2] = colours[1];
        }

        int[][] testBoard = {
                {2, 2, 2, 2, 1, 1, 2, 2},
                {2, 1, 2, 2, 1, 1, 1, 2},
                {1, 1, 2, 2, 1, 2, 2, 1},
                {2, 2, 2, 1, 2, 1, 1, 1},
                {2, 2, 1, 2, 1, 1, 1, 2},
                {1, 1, 1, 2, 2, 2, 2, 2},
                {1, 1, 1, 2, 2, 2, 2, 2},
                {1, 1, 1, 2, 1, 1, 1, 0}};
        //_board = testBoard;
    }

    public int[] getSize() {
        int[] size = {_m, _n};
        return size;
    }

    public LinkedList<int[]> canPlace(int y, int x, int colour) {
        LinkedList<int[]> eats = new LinkedList<int[]>();
        if (_board[y][x] != 0) return eats;
        int i;
        if (existsAnotherIn("u", y, x, colour)) {
            i = 1;
            while (isInBounds(y + i, x) && _board[y + i][x] != colour && _board[y + i][x] != 0) {
                int[] temp = {y + i, x};
                eats.add(temp);
                i++;
            }
        }
        if (existsAnotherIn("d", y, x, colour)) {
            i = 1;
            while (isInBounds(y - i, x) && _board[y - i][x] != colour && _board[y - i][x] != 0) {
                int[] temp = {y - i, x};
                eats.add(temp);
                i++;
            }       
        }
        if (existsAnotherIn("l", y, x, colour)) {
            i = 1;
            while (isInBounds(y, x - i) && _board[y][x - i] != colour && _board[y][x - i] != 0) {
                int[] temp = {y, x - i};
                eats.add(temp);
                i++;
            }
        }
        if (existsAnotherIn("r", y, x, colour)) {
            i = 1;
            while (isInBounds(y, x + i) && _board[y][x + i] != colour && _board[y][x + i] != 0) {
                int[] temp = {y, x + i};
                eats.add(temp);
                i++;
            }
        }
        if (existsAnotherIn("ul", y, x, colour)) {
            i = 1;
            while (isInBounds(y + i, x - i) && _board[y + i][x - i] != colour && _board[y + i][x - i] != 0) {
                int[] temp = {y + i, x - i};
                eats.add(temp);
                i++;
            }
        }
        if (existsAnotherIn("ur", y, x, colour)) {
            i = 1;
            while (isInBounds(y + i, x + i) && _board[y + i][x + i] != colour && _board[y + i][x + i] != 0) {
                int[] temp = {y + i, x + i};
                eats.add(temp);
                i++;
            }
        }
        if (existsAnotherIn("dl", y, x, colour)) {
            i = 1;
            while (isInBounds(y - i, x - i) && _board[y - i][x - i] != colour && _board[y - i][x - i] != 0) {
                int[] temp = {y - i, x - i};
                eats.add(temp);
                i++;
            }
        }
        if (existsAnotherIn("dr", y, x, colour)) {
            i = 1;
            while (isInBounds(y - i, x + i) && _board[y - i][x + i] != colour && _board[y - i][x + i] != 0) {
                int[] temp = {y - i, x + i};
                eats.add(temp);
                i++;
            }
        }
        return eats;
    }

    private boolean isInBounds(int i, int j) {
        return i >= 0 && j >= 0 && i < _m && j < _n;
    }

    private boolean existsAnotherIn(String lane, int vo, int ho, int colour) {
        int v = 0, h = 0;

        do {
            if ((v != 0 || h != 0) && _board[vo + v][ho + h] == colour) return true;

            if (lane.contains("u"))         v++;
            else if (lane.contains("d"))    v--;
            if (lane.contains("r"))         h++;
            else if (lane.contains("l"))    h--;
        } while (isInBounds(vo + v, ho + h) && _board[vo + v][ho + h] != 0);
        return false;
    }

    public int place(int y, int x, int colour) {
        LinkedList<int[]> stonesToEat = canPlace(y, x, colour);
        if (!stonesToEat.isEmpty()) {
            _board[y][x] = colour;
            for (int i = 0; i < stonesToEat.size(); i++) {
                int[] place = stonesToEat.get(i);
                _board[place[0]][place[1]] = colour;
            }
        }
        return stonesToEat.size();
    }

    public String toString() {
        String s = "";
        for (int i = 0; i < _board.length; i++) {
            for (int j = 0; j < _board[0].length; j++) {
                s+=_board[i][j]+"\t";
            }
            s += "\n";
        }
        return s;
    }

    public int stoneAt(int i, int j) {
        return _board[i][j];
    }
}

public static class Player {
    private String _name;
    private int _points;
    private int _colour;
    private int _ai;

    public Player(String name, int colour, int ai) {
        _name = name;
        _points = 0;
        _colour = colour;
        _ai = ai;
    }

    public void setScore(int s) {
        _points = s;
    }

    public Player(Player p) {
        _name = p._name;
        _points = p._points;
        _colour = p._colour;
        _ai = p._ai;
    }

    public boolean isAI() {
        return _ai != 0;
    }

    public void addPoints(int add) { _points += add; }

    public int getColour() { return _colour; }

    public String getName() { return _name; }

    public int getPoints() { return _points; }

    public int getAI() { return _ai; }
}

public class GameLog extends GameManager {
    private int _startingPlayer;
    private LinkedList<String> _moves;

    public GameLog(int startPlayer) {
        _startingPlayer = startPlayer;
        _moves = new LinkedList<String>();
    }

    public void addMove(String m) {
        _moves.add(m);
    }

    public int getStartingPlayer() { return _startingPlayer; }

    public LinkedList<String> getMoves() { return _moves; }
}
class MoveTimerListener implements ActionListener {
  private boolean flashOn = false;
  private int count;

  @Override
  public void actionPerformed(ActionEvent e) {
     flashOn = !flashOn;
     if (count >= MAX_COUNT) { // MAX_COUNT is an int constant
        // reached max -- stop timer
        ((Timer) e.getSource()).stop();
        flashOn = false;

        // TODO: place code to make move here
     }

     if (flashOn) {
        // TODO: place code to flash here
     }
     count++;
  }
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

@SuppressWarnings("serial")
public class FlashingTimerGui extends JPanel {
   private static final int MAX_COUNT = 20;
   private static final int IMG_WIDTH = 60;
   private static final int SIDES = 3;
   public static final int MOVE_TIMER_DELAY = 100;
   private Icon blankIcon;
   private Icon blackIcon;
   private Icon redIcon;
   private List<JLabel> labelList = new ArrayList<>();
   private Timer moveTimer;
   private int labelListIndex = 0;

   public FlashingTimerGui() {
      blankIcon = createIcon(new Color(0, 0, 0, 0));
      blackIcon = createIcon(Color.black);
      redIcon = createIcon(Color.red);

      JPanel gridPanel = new JPanel(new GridLayout(SIDES, SIDES));
      gridPanel.setBorder(BorderFactory.createLineBorder(Color.black));
      for (int i = 0; i < SIDES * SIDES; i++) {
         JLabel label = new JLabel(blankIcon);
         label.setBorder(BorderFactory.createLineBorder(Color.black));
         gridPanel.add(label);
         labelList.add(label);
      }

      JPanel buttonPanel = new JPanel();
      buttonPanel.add(new JButton(new MoveAction("Move")));

      setLayout(new BorderLayout());
      add(gridPanel, BorderLayout.CENTER);
      add(buttonPanel, BorderLayout.PAGE_END);

      labelList.get(labelListIndex).setIcon(blackIcon);
   }

   private Icon createIcon(Color color) {
      BufferedImage img = new BufferedImage(IMG_WIDTH, IMG_WIDTH,
            BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = img.createGraphics();
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setColor(color);
      int x = 4;
      int y = x;
      int w = IMG_WIDTH - 2 * x;
      int h = w;
      g2.fillOval(x, y, w, h);
      g2.dispose();
      return new ImageIcon(img);
   }

   private class MoveTimerListener implements ActionListener {
      private boolean flashOn = false;
      private int count;

      @Override
      public void actionPerformed(ActionEvent e) {
         flashOn = !flashOn;
         if (count >= MAX_COUNT) { // MAX_COUNT is an int constant
            // reached max -- stop timer
            ((Timer) e.getSource()).stop();
            flashOn = false;

            // code to make move here
            labelList.get(labelListIndex).setIcon(blankIcon);

            labelListIndex++;
            labelListIndex %= labelList.size();
            labelList.get(labelListIndex).setIcon(blackIcon);
         }

         if (flashOn) {
            labelList.get(labelListIndex).setIcon(redIcon);
         } else {
            labelList.get(labelListIndex).setIcon(blackIcon);
         }
         count++;
      }
   }

   private class MoveAction extends AbstractAction {

      public MoveAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         if (moveTimer != null && moveTimer.isRunning()) {
            // timer is running -- ignore request to re-run
            return;
         }

         moveTimer = new Timer(MOVE_TIMER_DELAY, new MoveTimerListener());
         moveTimer.start();
      }

   }

   private static void createAndShowGui() {
      FlashingTimerGui mainPanel = new FlashingTimerGui();

      JFrame frame = new JFrame("Flashing Timer");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }

}