我正在尝试使用 Java 的 Swing 库构建一个带有 GUI 界面的国际象棋游戏。当我开始游戏时,会打开一个带有棋盘的窗口。
我所坚持的是,每次我都想等待当前玩家采取行动,而不是无限地运行 while 循环,因为这不是很有效。
这是代码和之后的解释:
private void startGame()
{
while (!board.terminalBoard())
{
Move movePlayed = null;
// whilist making the move returns false, meaning we cant do it...
while (canMakeMove(movePlayed))
{
// TODO: Implement the getting move here
}
// If move is okay, make it
board.movePiece(movePlayed.getStart(), movePlayed.getEnd());
// Repaint the chessboard
chessboard.loadImages(board);
chessboard.repaintBoard();
currColor ^= Piece.BLACK;
}
}
Run Code Online (Sandbox Code Playgroud)
在内部 while 循环中,当用户所下的棋步无效时,它会再次迭代并等待下一个棋步。我不明白的是我如何等待玩家采取行动。
就我而言,玩家可以通过在棋盘上单击两次(源方格和目标方格)来进行移动。然后我的函数检查它是否有效。
如何等待用户在 Java Swing 窗口上单击两次?
编辑代码:问题是,如果我像你说的那样删除 thread.sleep,应用程序不会响应我的点击。
private void startGame()
{
while (!board.terminalBoard())
{
Move movePlayed = chessboard.getMove(board);
// whilist making the move returns false, meaning we cant do it...
if(canMakeMove(movePlayed))
{
// If move is okay, make it
board.movePiece(movePlayed.getStart(), movePlayed.getEnd());
// Repaint the chessboard
chessboard.loadImages(board);
chessboard.repaintBoard();
currColor ^= Piece.BLACK;
}
/* try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} */
}
}
Run Code Online (Sandbox Code Playgroud)
对于刚开始创建事件驱动程序的程序员来说,您陷入了一个常见陷阱:您将其编码为线性控制台程序,例如使用基于 System.in 和 println 的 Scanner 的程序,使用while 循环允许代码执行重复操作,而这在 GUI 编码中根本不起作用。相反,您应该通过侦听用户事件来等待用户输入,例如 ActionListeners 侦听按钮按下操作,或 MouseListeners 侦听鼠标操作,并且应该删除 while 循环。程序对用户输入的响应基于程序的状态(关键状态字段保存的值),而不是 while 循环。要使用的关键范例是:
所以在这里,这些字段可能类似于:
private boolean whitesTurn;
——如果是真的,听白棋走棋。如果为 false,则忽略白色的输入private ChessCell firstClick;
这可以保存获得第一次点击的单元格。如果为空,则玩家尚未进行第一次单击,但如果它不为空并且拥有一个可行的棋盘单元(无论您如何定义),则已进行第一次单击,下一次单击可能会在第二个位置例如,请参阅下面的代码。但请注意,为了简洁起见,此示例没有使用 MVC——模型-视图-控制器,但我建议您使用它。
import java.awt.*;
import java.awt.event.*;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class TestChess {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
private void createAndShowGUI() {
JFrame frame = new JFrame("Simple Chess");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new GameBoardPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
class GameBoardPanel extends JPanel {
public static final String WHITE = "WHITE";
public static final String BLACK = "BLACK";
public static final int ROWS = 8;
public static final int COLS = 8;
private JPanel[][] board = new JPanel[ROWS][COLS];
private JPanel boardPanel = new JPanel(new GridLayout(ROWS, COLS));
private JLabel whitePiece;
private JLabel blackPiece;
private JLabel statusLabel = new JLabel(WHITE);
private boolean isWhiteTurn = true;
private ChessCellPanel firstSelectedCell = null;
public GameBoardPanel() {
whitePiece = new JLabel(createIcon(new Color(240, 240, 240)));
blackPiece = new JLabel(createIcon(new Color(20, 20, 20)));
setLayout(new GridLayout(ROWS, COLS));
MyMouse myMouse = new MyMouse();
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
ChessCellPanel cellPanel = new ChessCellPanel(row, col);
cellPanel.addMouseListener(myMouse);
boardPanel.add(cellPanel);
board[row][col] = cellPanel;
}
}
addPiece(ROWS - 1, COLS - 1, whitePiece);
addPiece(0, 0, blackPiece);
JPanel statusPanel = new JPanel();
statusPanel.add(new JLabel("Turn: "));
statusPanel.add(statusLabel);
setLayout(new BorderLayout());
add(boardPanel);
add(statusPanel, BorderLayout.PAGE_END);
}
private class MyMouse extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
ChessCellPanel cellPanel = (ChessCellPanel) e.getSource();
if (cellPanel.getComponents().length > 0 && firstSelectedCell == null) {
JLabel piece = (JLabel) cellPanel.getComponent(0);
if (piece == (isWhiteTurn ? whitePiece : blackPiece)) {
firstSelectedCell = cellPanel;
cellPanel.setBackground(Color.YELLOW);
}
} else if (firstSelectedCell != null) {
if (cellPanel == firstSelectedCell) {
firstSelectedCell.setBackground(cellPanel.getCellColor());
firstSelectedCell = null;
} else {
cellPanel.removeAll();
cellPanel.add(firstSelectedCell.getComponent(0));
firstSelectedCell.removeAll();
firstSelectedCell.setBackground(firstSelectedCell.getCellColor());
firstSelectedCell = null;
isWhiteTurn = !isWhiteTurn;
statusLabel.setText(isWhiteTurn ? WHITE : BLACK);
}
boardPanel.revalidate();
boardPanel.repaint();
}
}
}
private void addPiece(int i, int j, JLabel piece) {
ChessCellPanel cellPanel = (ChessCellPanel) board[i][j];
cellPanel.add(piece);
}
private Icon createIcon(Color color) {
int width = ChessCellPanel.CELL_SIZE - 20;
int height = ChessCellPanel.CELL_SIZE - 20;
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(color);
g2d.fillOval(4, 4, width - 8, height - 8);
g2d.setStroke(new BasicStroke(3f));
g2d.setColor(Color.BLACK);
g2d.drawOval(4, 4, width - 8, height - 8);
g2d.dispose();
return new ImageIcon(img);
}
}
Run Code Online (Sandbox Code Playgroud)
class ChessCellPanel extends JPanel {
public static final int CELL_SIZE = 100;
private static final Color LIGHT_COLOR = new Color(240, 217, 181);
private static final Color DARK_COLOR = new Color(181, 136, 99);
private int row;
private int col;
private Color cellColor;
public ChessCellPanel(int row, int col) {
this.row = row;
this.col = col;
this.cellColor = (row + col) % 2 == 0 ? LIGHT_COLOR : DARK_COLOR;
setBackground(cellColor);
setLayout(new GridBagLayout());
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
public Color getCellColor() {
return cellColor;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(CELL_SIZE, CELL_SIZE);
}
}
Run Code Online (Sandbox Code Playgroud)
此示例的关键在于 MouseListener(实际上是 MouseAdapter),它执行以下操作:
firstSelectedCell
另外,如果没有选择棋子,则关键状态变量为空firstSelectedCell
使用该单元设置状态字段isWhiteTurn
@Override
public void mousePressed(MouseEvent e) {
ChessCellPanel cellPanel = (ChessCellPanel) e.getSource(); //1
// 2
if (cellPanel.getComponents().length > 0 && firstSelectedCell == null) {
// 3
JLabel piece = (JLabel) cellPanel.getComponent(0);
if (piece == (isWhiteTurn ? whitePiece : blackPiece)) {
firstSelectedCell = cellPanel;
cellPanel.setBackground(Color.YELLOW);
}
} else if (firstSelectedCell != null) {
// 4
if (cellPanel == firstSelectedCell) {
// 5
firstSelectedCell.setBackground(cellPanel.getCellColor());
firstSelectedCell = null;
} else {
// 6
cellPanel.removeAll();
cellPanel.add(firstSelectedCell.getComponent(0));
firstSelectedCell.removeAll();
firstSelectedCell.setBackground(firstSelectedCell.getCellColor());
firstSelectedCell = null;
isWhiteTurn = !isWhiteTurn;
statusLabel.setText(isWhiteTurn ? WHITE : BLACK);
}
// 7
boardPanel.revalidate();
boardPanel.repaint();
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
97 次 |
最近记录: |