上一篇
Java棋盘绘制棋子技巧,Java实现棋子棋盘绘制,快速实现Java棋盘棋子绘制
- 后端开发
- 2025-06-01
- 3785
在Java中绘制棋盘和棋子,通常使用Swing或JavaFX的绘图功能,通过重写组件的
paintComponent()
方法,利用Graphics2D对象绘制棋盘网格和圆形棋子,棋子坐标需根据网格尺寸计算,通过
fillOval()
在指定位置渲染棋子颜色实现落子效果。
Java棋盘棋子绘制教程:实现图形化棋盘与落子功能
在Java中创建棋盘并在其上绘制棋子是一个常见的图形界面编程任务,本教程将详细介绍实现方法,涵盖Swing组件的使用、绘图技术和交互事件处理。
实现思路
我们将采用以下技术方案:
- 使用
JFrame
创建主窗口 - 自定义
JPanel
作为棋盘绘制区域 - 重写
paintComponent
方法绘制棋盘和棋子 - 使用鼠标事件监听器实现交互式落子
- 设计美观的UI界面增强用户体验
完整代码实现
import javax.swing.*; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.Ellipse2D; import java.util.ArrayList; import java.util.List; public class ChessBoard extends JFrame { // 棋盘设置 private static final int BOARD_SIZE = 15; // 15x15的棋盘 private static final int GRID_SIZE = 40; // 每个格子的像素大小 private static final int MARGIN = 50; // 边距 private static final int WINDOW_SIZE = 2 * MARGIN + (BOARD_SIZE - 1) * GRID_SIZE; // 棋子数据 private enum Piece { EMPTY, BLACK, WHITE } private Piece[][] board = new Piece[BOARD_SIZE][BOARD_SIZE]; private List<Point> moveHistory = new ArrayList<>(); private Color boardColor = new Color(220, 179, 92); // 棋盘木质颜色 private boolean isBlackTurn = true; // 当前落子方(黑子先行) private JLabel statusLabel; // 状态标签 public ChessBoard() { setTitle("Java 棋盘棋子绘制"); setSize(WINDOW_SIZE, WINDOW_SIZE + 60); // 额外高度用于状态栏 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); // 居中显示 // 初始化棋盘 for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { board[i][j] = Piece.EMPTY; } } // 创建棋盘面板 BoardPanel boardPanel = new BoardPanel(); boardPanel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { // 计算点击位置对应的棋盘坐标 int x = (e.getX() - MARGIN + GRID_SIZE / 2) / GRID_SIZE; int y = (e.getY() - MARGIN + GRID_SIZE / 2) / GRID_SIZE; // 确保坐标在有效范围内且该位置没有棋子 if (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE && board[x][y] == Piece.EMPTY) { board[x][y] = isBlackTurn ? Piece.BLACK : Piece.WHITE; moveHistory.add(new Point(x, y)); isBlackTurn = !isBlackTurn; // 切换玩家 updateStatus(); boardPanel.repaint(); // 重绘棋盘 } } }); // 创建状态标签 statusLabel = new JLabel(" ", JLabel.CENTER); statusLabel.setFont(new Font("微软雅黑", Font.BOLD, 16)); statusLabel.setForeground(new Color(50, 50, 50)); statusLabel.setOpaque(true); statusLabel.setBackground(new Color(240, 240, 240)); updateStatus(); // 添加组件 setLayout(new BorderLayout()); add(boardPanel, BorderLayout.CENTER); add(statusLabel, BorderLayout.SOUTH); // 添加重置按钮 JButton resetButton = new JButton("重新开始"); resetButton.setFont(new Font("微软雅黑", Font.PLAIN, 14)); resetButton.setBackground(new Color(70, 130, 180)); resetButton.setForeground(Color.WHITE); resetButton.addActionListener(e -> resetGame()); JPanel buttonPanel = new JPanel(); buttonPanel.add(resetButton); add(buttonPanel, BorderLayout.NORTH); } private void updateStatus() { String player = isBlackTurn ? "黑方" : "白方"; statusLabel.setText(player + "回合 | 落子位置: " + (moveHistory.isEmpty() ? "无" : formatPoint(moveHistory.get(moveHistory.size()-1)))); } private String formatPoint(Point p) { char col = (char)('A' + p.x); return String.format("%c%d", col, p.y + 1); } private void resetGame() { for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { board[i][j] = Piece.EMPTY; } } moveHistory.clear(); isBlackTurn = true; updateStatus(); repaint(); } // 自定义棋盘绘制面板 private class BoardPanel extends JPanel { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 绘制棋盘背景 g2d.setColor(boardColor); g2d.fillRect(0, 0, getWidth(), getHeight()); // 绘制网格线 g2d.setColor(Color.BLACK); for (int i = 0; i < BOARD_SIZE; i++) { int startX = MARGIN + i * GRID_SIZE; int startY = MARGIN; int endY = MARGIN + (BOARD_SIZE - 1) * GRID_SIZE; // 竖线 g2d.drawLine(startX, startY, startX, endY); // 横线 int startY2 = MARGIN + i * GRID_SIZE; int endX = MARGIN + (BOARD_SIZE - 1) * GRID_SIZE; g2d.drawLine(MARGIN, startY2, endX, startY2); } // 绘制天元和星位 drawBoardMarkers(g2d); // 绘制棋子 for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { if (board[i][j] != Piece.EMPTY) { drawPiece(g2d, i, j); } } } } private void drawBoardMarkers(Graphics2D g2d) { g2d.setColor(Color.BLACK); int center = BOARD_SIZE / 2; int size = 8; // 绘制九个星位 int[] points = {3, center, BOARD_SIZE - 4}; for (int x : points) { for (int y : points) { g2d.fillOval( MARGIN + x * GRID_SIZE - size/2, MARGIN + y * GRID_SIZE - size/2, size, size ); } } } private void drawPiece(Graphics2D g2d, int x, int y) { int centerX = MARGIN + x * GRID_SIZE; int centerY = MARGIN + y * GRID_SIZE; int radius = GRID_SIZE / 2 - 2; if (board[x][y] == Piece.BLACK) { // 绘制黑色棋子(带光泽效果) GradientPaint gradient = new GradientPaint( centerX - radius/2, centerY - radius/2, Color.DARK_GRAY, centerX + radius/2, centerY + radius/2, Color.BLACK ); g2d.setPaint(gradient); g2d.fill(new Ellipse2D.Double(centerX - radius, centerY - radius, radius*2, radius*2)); // 绘制光泽 g2d.setColor(new Color(255, 255, 255, 150)); g2d.fillOval(centerX - radius/3, centerY - radius/3, radius/2, radius/3); } else { // 绘制白色棋子(带阴影效果) g2d.setColor(Color.WHITE); g2d.fill(new Ellipse2D.Double(centerX - radius, centerY - radius, radius*2, radius*2)); // 绘制边框和阴影 g2d.setColor(new Color(150, 150, 150)); g2d.setStroke(new BasicStroke(1.5f)); g2d.drawOval(centerX - radius, centerY - radius, radius*2, radius*2); // 底部阴影 g2d.setColor(new Color(200, 200, 200)); g2d.drawArc(centerX - radius, centerY - radius, radius*2, radius*2, 200, 140); } } } public static void main(String[] args) { SwingUtilities.invokeLater(() -> { new ChessBoard().setVisible(true); }); } }
关键实现解析
棋盘网格绘制
通过计算棋盘位置,使用drawLine
方法在面板上绘制横线和竖线:
for (int i = 0; i < BOARD_SIZE; i++) { int startX = MARGIN + i * GRID_SIZE; // 绘制竖线 g2d.drawLine(startX, startY, startX, endY); // 绘制横线 g2d.drawLine(MARGIN, startY2, endX, startY2); }
棋子绘制技术
使用Ellipse2D.Double
绘制圆形棋子,并添加渐变和光泽效果增强视觉效果:
黑色棋子:
GradientPaint gradient = new GradientPaint( centerX - radius/2, centerY - radius/2, Color.DARK_GRAY, centerX + radius/2, centerY + radius/2, Color.BLACK ); g2d.setPaint(gradient); g2d.fill(new Ellipse2D.Double(centerX - radius, centerY - radius, radius*2, radius*2));
白色棋子:
g2d.setColor(Color.WHITE); g2d.fill(new Ellipse2D.Double(centerX - radius, centerY - radius, radius*2, radius*2));
鼠标交互实现
通过添加鼠标事件监听器实现点击落子功能:
boardPanel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { // 计算点击位置对应的棋盘坐标 int x = (e.getX() - MARGIN + GRID_SIZE / 2) / GRID_SIZE; int y = (e.getY() - MARGIN + GRID_SIZE / 2) / GRID_SIZE; // 落子逻辑 if (isValidPosition(x, y)) { board[x][y] = isBlackTurn ? Piece.BLACK : Piece.WHITE; // 更新界面状态 } } });
游戏状态管理
使用二维数组存储棋盘状态,记录落子历史:
private Piece[][] board = new Piece[BOARD_SIZE][BOARD_SIZE]; private List<Point> moveHistory = new ArrayList<>();
使用指南
- 运行程序后,将显示一个15×15的围棋棋盘
- 黑色方先行,点击交叉点放置棋子
- 落子后自动切换玩家
- 状态栏显示当前回合信息
- 点击”重新开始”按钮重置棋盘
扩展建议
- 游戏规则实现:添加围棋规则判定(如提子、禁着点等)
- 保存/加载功能:实现棋局保存和读取
- AI对手:添加简单的人工智能实现人机对战
- 网络对战:通过Socket编程实现网络对战功能
此实现使用了Java Swing框架进行图形界面开发,遵循了面向对象的设计原则,代码结构清晰,可扩展性强。
参考资料
- Java官方Swing教程:https://docs.oracle.com/javase/tutorial/uiswing/
- Java 2D图形编程指南:https://docs.oracle.com/javase/tutorial/2d/index.html
- 《Java核心技术卷I》第10章 – 图形程序设计
本文提供的代码在Java 8及以上环境测试通过,使用Swing图形库实现棋盘棋子的绘制和交互功能。