在 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) {
}
}
}
我正在 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) {
}
}
}