在 Board (JPanel) 中模拟鼠标点击

Simulate a mouse click within Board (JPanel)

我正在 java 中编写一个简单的 TicTacToe 游戏。 基本实现已经完成。 Player vs Player 运行完美。

但是现在,当我实现 AI 时,我遇到了问题。 我已经计算了计算机的移动,但我无法让计算机单击 JPanel 上的那个位置 [使用 (x, y) 坐标]。

我看到了机器人class,但是它没有点击需要的地方,而且好像点击了window以外的地方。

这是在 JPanel 上绘制板的代码:

private class Board extends JPanel{
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public Board(){
            this.setSize(new Dimension(board_width, board_height));
            this.setPreferredSize(new Dimension(board_width, board_height));
            this.setBackground(new Color(0x84ACFF));            
            this.setOpaque(true);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            //g.setColor(new Color(0xf9d1af));
            g.setColor(Color.white);
            g.drawLine((board_width/3), 0, (board_width/3), board_height);
            g.drawLine((board_width/3)*2, 0, (board_width/3)*2, board_height);
            g.drawLine(0, (board_height/3), (board_width), (board_height/3));
            g.drawLine(0, (board_height/3)*2, (board_width), (board_height/3)*2);
            g.finalize();
        }
    }

这是我在 JPanel 中使用的 mouseListener:

@Override
public void mousePressed(MouseEvent e) {
    Graphics g = this.getGraphics();

    int X = e.getX();
    int Y = e.getY();

    //JOptionPane.showMessageDialog(null, e.getXOnScreen()+":"+e.getYOnScreen());

    int block_x = board_width/3;
    int block_y = board_height/3;

    X = X/block_x;
    Y = Y/block_y;

    //For array Assignment
    Click_X = Y;
    Click_Y = X;

    //Keep copy of the originals
    Orig_X = X;
    Orig_Y = Y;

    //------------------------------------------
    //          Assign to array & Draw
    //------------------------------------------
    if (computer){
        if (start.equals("Computer")){
            if (game_board[Click_X][Click_Y] != ' ') return;
            moves++;
            game_board[Click_X][Click_Y] = Cross;
            drawCross(((X+1)*block_x)+25, ((Y+1)*block_y)+25, 50, 50, g);
            dcsn = new Decision(game_board, moves);
        }
        else{
            if (game_board[Click_X][Click_Y] != ' ') return;
            moves++;
            game_board[Click_X][Click_Y] = Nought;
            drawNought(((X+1)*block_x), ((Y+1)*block_y), 50, 50, g);
            dcsn = new Decision(game_board, moves);
        }
    }
    else{
        if (start.equals("Human")){
            if (game_board[Click_X][Click_Y] != ' ') return;
            moves++;
            game_board[Click_X][Click_Y] = Cross;
            drawCross(((X+1)*block_x)+25, ((Y+1)*block_y)+25, 50, 50, g);
            dcsn = new Decision(game_board, moves);
        }
        else{
            if (game_board[Click_X][Click_Y] != ' ') return;
            moves++;
            game_board[Click_X][Click_Y] = Nought;
            drawNought(((X+1)*block_x), ((Y+1)*block_y), 50, 50, g);
            dcsn = new Decision(game_board, moves);
        }
    }

    switch (dcsn.gameOver()){
    case "X":
        JOptionPane.showMessageDialog(null,"X has won!");
        break;
    case "O":
        JOptionPane.showMessageDialog(null,"O has won!");
        break;
    case "draw":
        JOptionPane.showMessageDialog(null,"Draw!");
        break;
    case " ":
        break;
    }

    switchTurn();
}

现在如何让计算机点击计算出的位置? 有什么想法吗?

这里是 link 完整的源代码: Download Source

否则很难重现这种情况。

我想给你一个例子,说明如何按照我在评论中建议的那样去做。 ("你为什么不为每个单元格添加一个 MouseListener", "你不需要机器人 class" ) 当然你不必这样做,但我认为它更容易编码和理解。现在计算机只是随机选择单元格,没有 restart/win/lose,我只是想向您展示这个概念。 在这种情况下我不会使用机器人 class,程序应该无法控制光标 ;)

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
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.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.LineBorder;

public class TicTacToe {

    Cell[][] cells = new Cell[3][3];
    boolean humanTurn = true;

    public TicTacToe() {

        JFrame frame = new JFrame("T I C - T A C - T O E");

        JPanel panel = new JPanel(new GridLayout(3, 3));
        addCells(panel);

        frame.add(panel);

        frame.setSize(600, 600);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        ActionListener actionListener = new ActionListener() {

            Random r = new Random();

            @Override
            public void actionPerformed(ActionEvent e) {

                if (!humanTurn) {
                    // Random cell
                    int x = r.nextInt(3);
                    int y = r.nextInt(3);
                    Cell cell = cells[x][y];

                    if (!cell.clicked) {

                        // Only the computer runs the gameloop, so false
                        cell.human = false;
                        cell.cross = false;

                        cell.repaint();

                        // Make sure the panel repaints before setting next
                        // booleans
                        EventQueue.invokeLater(new Runnable() {
                            public void run() {
                                humanTurn = true;
                                cell.clicked = true;
                            }
                        });
                    }
                }

            }
        };
        Timer gameloop = new Timer(10, actionListener);
        gameloop.start();

    }

    private void addCells(JPanel panel) {

        for (int y = 0; y < 3; y++) {
            for (int x = 0; x < 3; x++) {

                Cell cell = new Cell();
                cell.setBorder(new LineBorder(Color.BLACK));

                cells[x][y] = cell;

                panel.add(cell);

            }
        }
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                new TicTacToe();
            }
        });

    }

    class Cell extends JPanel implements MouseListener {

        boolean clicked = false;
        boolean human = true;
        boolean cross = false;

        public Cell() {

            addMouseListener(this);

        }

        @Override
        public void paintComponent(Graphics g) {

            super.paintComponent(g);

            Graphics2D gg = (Graphics2D) g;

            // Makes drawing smooth
            gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            // Drawing blue cross (player)
            if (human && cross) {
                gg.setColor(Color.BLUE);
                gg.drawLine(20, 20, getWidth() - 20, getHeight() - 20);
                gg.drawLine(getWidth() - 20, 20, 20, getHeight() - 20);
            }

            // Drawing red circle (computer)
            else if (!human && !cross) {
                gg.setColor(Color.RED);
                gg.drawOval(10, 10, getWidth() - 20, getHeight() - 20);
            }

        }

        @Override
        public void mouseClicked(MouseEvent arg0) {

            if (humanTurn && !clicked) {

                // Only human can click on the panel, so true
                human = true;
                cross = true;

                repaint();

                // Make sure the panel repaints before setting next booleans
                EventQueue.invokeLater(new Runnable() {
                    public void run() {
                        humanTurn = false;
                        clicked = true;
                    }
                });

            }

        }

        @Override
        public void mouseEntered(MouseEvent arg0) {

        }

        @Override
        public void mouseExited(MouseEvent arg0) {

        }

        @Override
        public void mousePressed(MouseEvent arg0) {

        }

        @Override
        public void mouseReleased(MouseEvent arg0) {

        }

    }

}