基于JFrame和JPanel的Java象棋棋子移动规则实现咨询
象棋棋子移动规则实现方案建议
核心设计思路
基于多态特性,在抽象父类ChessPiece中定义用于判断移动合法性的抽象方法,每个棋子子类(Pawn、King等)重写该方法,实现各自的专属移动规则。主逻辑中只需统一调用该方法,即可完成不同棋子的合法性校验。
步骤1:重构ChessPiece类
将ChessPiece改为抽象类,封装基础属性并添加抽象校验方法:
public abstract class ChessPiece { protected String color; // 例如"black"或"white" protected int x; protected int y; public ChessPiece(String color, int x, int y) { this.color = color; this.x = x; this.y = y; } // 抽象方法:判断从(fromX, fromY)到(toX, toY)的移动是否合法 // board参数用于获取棋盘其他棋子信息,判断阻挡或吃子规则 public abstract boolean isValidMove(int fromX, int fromY, int toX, int toY, ChessPiece[][] board); // getter/setter方法 public String getColor() { return color; } public int getX() { return x; } public int getY() { return y; } public void setPosition(int x, int y) { this.x = x; this.y = y; } }
步骤2:Pawn(兵)类的移动规则实现
中国象棋兵规则实现
- 未过河:仅能向前走1格,不可左右移动,目标位置需为空
- 过河后:可向前、左、右走1格,目标位置可为空或敌方棋子
public class Pawn extends ChessPiece { public Pawn(String color, int x, int y) { super(color, x, y); } @Override public boolean isValidMove(int fromX, int fromY, int toX, int toY, ChessPiece[][] board) { // 校验目标位置是否在棋盘范围内 if (toX < 0 || toX >= 9 || toY < 0 || toY >= 10) return false; ChessPiece targetPiece = board[toY][toX]; // 目标位置不能是己方棋子 if (targetPiece != null && targetPiece.getColor().equals(this.color)) return false; int xDiff = Math.abs(toX - fromX); int yDiff = Math.abs(toY - fromY); // 黑兵(初始位于y≥7)逻辑 if (this.color.equals("black")) { if (fromY >= 5) { // 未过河:仅向前走1格,x坐标不变,目标为空 return xDiff == 0 && toY == fromY - 1 && targetPiece == null; } else { // 过河后:上下左右1格范围内,目标为空或敌方棋子 return yDiff == 1 && xDiff <= 1 && (targetPiece == null || !targetPiece.getColor().equals(this.color)); } } // 白兵(初始位于y≤2)逻辑 else if (this.color.equals("white")) { if (fromY <= 4) { return xDiff == 0 && toY == fromY + 1 && targetPiece == null; } else { return yDiff == 1 && xDiff <= 1 && (targetPiece == null || !targetPiece.getColor().equals(this.color)); } } return false; } }
国际象棋兵规则实现
- 普通移动:向前走1格,目标位置为空
- 初始移动:未移动过的兵可向前走2格,路径无阻挡
- 吃子规则:斜向走1格,目标为敌方棋子
public class Pawn extends ChessPiece { public Pawn(String color, int x, int y) { super(color, x, y); } @Override public boolean isValidMove(int fromX, int fromY, int toX, int toY, ChessPiece[][] board) { if (toX < 0 || toX >= 8 || toY < 0 || toY >= 8) return false; ChessPiece target = board[toY][toX]; int yDirection = this.color.equals("white") ? 1 : -1; // 白兵向上,黑兵向下 // 普通向前移动 if (toX == fromX && toY == fromY + yDirection && target == null) { return true; } // 初始2格移动 if (toX == fromX && toY == fromY + 2 * yDirection) { boolean isInitialPos = (this.color.equals("white") && fromY == 1) || (this.color.equals("black") && fromY == 6); return isInitialPos && board[fromY + yDirection][fromX] == null && target == null; } // 斜向吃子 if (Math.abs(toX - fromX) == 1 && toY == fromY + yDirection) { return target != null && !target.getColor().equals(this.color); } return false; } }
步骤3:King(王)类的移动规则实现
中国象棋王规则实现
- 仅能在九宫格内移动(黑王:y≥7,3≤x≤5;白王:y≤2,3≤x≤5)
- 每次仅能走1格(上下左右)
public class King extends ChessPiece { public King(String color, int x, int y) { super(color, x, y); } @Override public boolean isValidMove(int fromX, int fromY, int toX, int toY, ChessPiece[][] board) { // 校验九宫格范围 if (this.color.equals("black")) { if (toY < 7 || toX < 3 || toX > 5) return false; } else { if (toY > 2 || toX < 3 || toX > 5) return false; } ChessPiece target = board[toY][toX]; if (target != null && target.getColor().equals(this.color)) return false; // 仅能走1格(上下左右) int xDiff = Math.abs(toX - fromX); int yDiff = Math.abs(toY - fromY); return (xDiff == 1 && yDiff == 0) || (xDiff == 0 && yDiff == 1); } }
国际象棋王规则实现
- 可向8个方向走1格
- 目标位置不能是己方棋子
public class King extends ChessPiece { public King(String color, int x, int y) { super(color, x, y); } @Override public boolean isValidMove(int fromX, int fromY, int toX, int toY, ChessPiece[][] board) { if (toX < 0 || toX >= 8 || toY < 0 || toY >= 8) return false; ChessPiece target = board[toY][toX]; if (target != null && target.getColor().equals(this.color)) return false; // 8个方向1格范围(排除原地不动) int xDiff = Math.abs(toX - fromX); int yDiff = Math.abs(toY - fromY); return (xDiff <= 1 && yDiff <= 1) && !(xDiff == 0 && yDiff == 0); } }
步骤4:在App.java中整合校验逻辑
在处理用户移动操作时,调用棋子的isValidMove方法判断合法性,合法则执行移动:
// 假设获取到起始位置(startX, startY)和目标位置(targetX, targetY) ChessPiece selectedPiece = board[startY][startX]; if (selectedPiece != null) { if (selectedPiece.isValidMove(startX, startY, targetX, targetY, board)) { // 执行移动逻辑 board[targetY][targetX] = selectedPiece; board[startY][startX] = null; selectedPiece.setPosition(targetX, targetY); // 刷新棋盘UI repaint(); } else { // 提示非法移动 System.out.println("非法移动!"); } }
额外注意事项
- 路径阻挡校验:车、马、象等棋子需额外判断移动路径上是否有其他棋子阻挡(Pawn和King基本无需处理,除国际象棋兵的初始2格)
- 特殊规则:中国象棋"王不见王"、国际象棋"王车易位"等规则,需在主逻辑或对应棋子类中额外实现
- 坐标一致性:确保棋盘行/列的坐标定义统一,避免方向逻辑错误
内容的提问来源于stack exchange,提问作者RICCARDO PICCO
相关产品推荐
相关产品推荐

