【问题标题】:Simulate a mouse click within Board (JPanel)在 Board (JPanel) 中模拟鼠标点击
【发布时间】:2015-09-06 09:44:51
【问题描述】:

我正在用 java 编写一个简单的井字游戏。 基本实现就完成了。 Player vs Player 工作完美。

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

看过Robot类,但是没有点击到需要的地方,好像是在窗口外点击了。

这是在 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();
}

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

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

否则很难重现这种情况。

【问题讨论】:

  • 1) 为什么不为每个单元格添加一个 MouseListener?会让事情变得更容易和更清晰(你不需要机器人课程)。 2)请考虑发布MCVE(或SSCCE),我无法重现您的问题。 3)Click_X = Y; Click_Y = X;不应该是Click_X = X; Click_Y = Y;吗?
  • 您可以创建一个方法 assignToArrayAndDraw(),您可以从 mousePressed() 方法或您的 AI 中调用该方法。
  • @LuxxMiner :不,Click_X = Y 没问题,因为我需要 [(00),(01),(02)] 格式的东西,用于将交叉/空值存储在数组中.
  • 我已经添加了源代码,否则在这种情况下很难发布 MCVE。 @LuxxMiner。
  • 重点是不需要机器人点击板子。你的 AI 应该直接调用 mousePressed() 中的代码(除非你应该将此代码打包到另一个方法中,这将独立于鼠标坐标 - 它只会使用网格坐标)

标签: java swing graphics mouselistener tic-tac-toe


【解决方案1】:

我想给你一个例子,告诉你如何按照我在 cmets 中的建议去做。 (“你为什么不为每个单元格添加一个 MouseListener”,“你不需要机器人类”)当然你不必这样做这样,但我认为它更容易编码和理解。现在计算机只是选择随机单元格并且没有重新启动/赢/输,我只是想向您展示这个概念。 在这种情况下我不会使用机器人类,程序应该无法控制光标;)

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) {

        }

    }

}

【讨论】:

    猜你喜欢
    • 2017-04-17
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 2011-12-30
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多