你想要建模一场象棋,包括棋盘,方块和棋子。对于这个问题,您需要对棋盘建模(作为二维棋盘数组);棋盘上的每个棋盘子可以是空的,也可以包含一个棋子。棋子依次有颜色和它在棋盘上的当前位置。
a.有一个抽象类ChessPiece,它提供了一个具体的方法和属性来表示棋子的位置,还有一个抽象方法isMoveLegal。
b.你从ChessPiece继承了许多具体的类。,卒,车,骑士等),他们的责任是提供一个具体的实现是MoveLegal为自己的特点。
c.设置单板的启动状态。
d.允许玩家指定一个移动。
e.检查移动是否有效。
f.如果下步有效,则下步,更新所涉及的棋子,更新棋盘,并将棋盘显示给玩家。
国际象棋,不是中国象棋
提供参考链接,期望对你有所帮助:https://blog.csdn.net/qq_40869977/article/details/122947387
【博文代码注解详细,值得借鉴】
你好,如果只是实现基本的棋盘与走法的话,还算好的。如果是全部的程序还是很多的。。
这个是一个基本的java国际象棋文章,你查看下:https://blog.csdn.net/Darvec/article/details/99708817
推荐一个基于javaFx的象棋类实现源码,地址:https://www.nhooo.com/note/qa3eqc.html
@Slf4j
public class BoardPanel extends JPanel implements LambdaMouseListener {
/**
* 用于标记棋盘走棋痕迹
*/
private final transient TraceMarker traceMarker;
/**
* 当前走棋开始坐标位置对应棋子
*/
private transient ChessPiece curFromPiece;
/**
* 场景
*/
private transient Situation situation;
/**
* Create the panel.
*/
public BoardPanel() {
setBorder(new EmptyBorder(5, 5, 5, 5));
setLayout(null);
// 初始化标记符
traceMarker = new TraceMarker(BoardPanel.this);
// 添加鼠标事件
addMouseListener(this);
}
/**
* 更新标记
*/
public void updateMark(Place from, Place to) {
// 更新标记
curFromPiece = null;
// 更改标记
traceMarker.endedStep(from, to);
}
/**
* 初始化所有标记
*/
public void initMark() {
traceMarker.initMarker();
}
/**
* 添加棋子
*/
public void init(Situation situation) {
this.situation = situation;
// 移除所有组件
this.removeAll();
// 添加棋子
situation.getPieceList().forEach(it -> add(it.getComp()));
situation.getSituationRecord().getEatenPieceList().forEach(it -> add(it.getComp()));
// 初始化标记符
traceMarker.initMarker();
repaint();
}
/**
* @param e 鼠标按压事件对象
*/
@Override
public void mouseReleased(MouseEvent e) {
// 位置
Place pointerPlace = ChessDefined.convertLocationToPlace(e.getPoint());
if (pointerPlace == null) {
return;
}
if (situation.winner() != null) {
log.warn("已经存在胜利者: {}, 无法走棋", situation.winner());
return;
}
// 当前走棋方
@NonNull Part pointerPart = situation.getNextPart();
// 当前焦点棋子
ChessPiece pointerPiece = situation.getChessPiece(pointerPlace);
// 通过当前方和当前位置判断是否可以走棋
// step: form
if (curFromPiece == null) {
// 当前焦点位置有棋子且是本方棋子
if (pointerPiece != null && pointerPiece.piece.part == pointerPart) {
// 本方棋子, 同时是from指向
curFromPiece = pointerPiece;
traceMarker.setMarkFromPlace(pointerPlace);
// 获取toList
MyList<Place> list = curFromPiece.piece.role.find(new AnalysisBean(situation.generatePieces()), pointerPart, pointerPlace);
traceMarker.showMarkPlace(list);
ChessAudio.CLICK_FROM.play();
log.info("true -> 当前焦点位置有棋子且是本方棋子");
final ListPool listPool = ListPool.localPool();
listPool.addListToPool(list);
return;
}
log.warn("warning -> from 焦点指示错误");
return;
}
if (pointerPlace.equals(curFromPiece.getPlace())) {
log.warn("false -> from == to");
return;
}
// 当前焦点位置有棋子且是本方棋子
if (pointerPiece != null && pointerPiece.piece.part == pointerPart) {
assert curFromPiece.piece.part == pointerPart : "当前焦点位置有棋子且是本方棋子 之前指向了对方棋子";
// 更新 curFromPiece
curFromPiece = pointerPiece;
traceMarker.setMarkFromPlace(pointerPlace);
MyList<Place> list = curFromPiece.piece.role.find(new AnalysisBean(situation.generatePieces()), pointerPart, pointerPlace);
traceMarker.showMarkPlace(list);
ChessAudio.CLICK_FROM.play();
log.info("true -> 更新 curFromPiece");
ListPool.localPool().addListToPool(list);
return;
}
final StepBean stepBean = StepBean.of(curFromPiece.getPlace(), pointerPlace);
// 如果不符合规则则直接返回
final Piece[][] pieces = situation.generatePieces();
if (!curFromPiece.piece.role.rule.check(pieces, pointerPart, stepBean.from, stepBean.to)) {
// 如果当前指向棋子是本方棋子
log.warn("不符合走棋规则");
return;
}
// 如果达成长拦或者长捉, 则返回
final StepBean forbidStepBean = situation.getForbidStepBean();
if (forbidStepBean != null && forbidStepBean.from == stepBean.from && forbidStepBean.to == stepBean.to) {
ChessAudio.MAN_MOV_ERROR.play();
log.warn("长拦或长捉");
return;
}
AnalysisBean analysisBean = new AnalysisBean(pieces);
// 如果走棋后, 导致两个 BOSS 对面, 则返回
if (!analysisBean.isBossF2FAfterStep(curFromPiece.piece, stepBean.from, stepBean.to)) {
ChessAudio.MAN_MOV_ERROR.play();
log.warn("BOSS面对面");
return;
}
/* 模拟走一步棋, 之后再计算对方再走一步是否能够吃掉本方的 boss */
if (analysisBean.simulateOneStep(stepBean, bean -> bean.canEatBossAfterOneAiStep(Part.getOpposite(pointerPart)))) {
ChessAudio.MAN_MOV_ERROR.play();
log.warn("BOSS 危险");
if (!Application.config().isActiveWhenBeCheck()) {
return;
}
}
// 当前棋子无棋子或者为对方棋子, 且符合规则, 可以走棋
Object[] objects = new Object[]{stepBean.from, stepBean.to, PlayerType.PEOPLE};
final boolean sendSuccess = Application.context().getCommandExecutor().sendCommandWhenNotRun(CommandExecutor.CommandType.LocationPiece, objects);
if (!sendSuccess) {
log.warn("命令未发送成功: {} ==> {}", CommandExecutor.CommandType.LocationPiece, Arrays.toString(objects));
}
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Image img = ChessImage.CHESS_BOARD.getImage();
int imgWidth = img.getWidth(this);
int imgHeight = img.getHeight(this);// 获得图片的宽度与高度
int fWidth = getWidth();
int fHeight = getHeight();// 获得窗口的宽度与高度
int x = (fWidth - imgWidth) / 2;
int y = (fHeight - imgHeight) / 2;
// 520 576 514 567
log.debug(String.format("%s,%s,%s,%s,%s,%s", imgWidth, imgHeight, fWidth, fHeight, x, y));
g.drawImage(img, 0, 0, null);
}
}
博主参考下下面的链接
https://b23.tv/Kzz9U4s
https://www.jb51.net/article/161774.htm
经过实测,此方案是可行的,可以参考下,代码是链接中国际象棋的;
import java.applet.Applet;
import java.awt.Graphics;
public class ChessBoard extends Applet{
public void init(){
setSize(400,400);
this.setVisible(true);
}
public void paint(Graphics g){
g.drawRect(20, 10, 320, 320);
g.drawLine(60, 10, 60, 330); //第一条竖线;
g.drawLine(100,10,100,330); //第二条竖线;
g.drawLine(140, 10, 140, 330); //第三条竖线;
g.drawLine(180, 10, 180, 330);
g.drawLine(220,10,220,330);
g.drawLine(260, 10, 260, 330);
g.drawLine(300,10,300,330);
// g.drawLine(340,10,340,330);
/绘制横线/
g.drawLine(20,50,340,50); //第一条横线;
g.drawLine(20,90,340,90);
g.drawLine(20,130,340,130);
g.drawLine(20,170,340,170);
g.drawLine(20,210,340,210);
g.drawLine(20,250,340,250);
g.drawLine(20,290,340,290);
/填充黑框/
g.fillRect(20, 10,40, 40);
g.fillRect(100, 10,40, 40);
g.fillRect(180, 10,40, 40);
g.fillRect(260, 10,40, 40);
g.fillRect(60, 50,40, 40);
g.fillRect(140, 50,40, 40);
g.fillRect(220, 50,40, 40);
g.fillRect(300, 50,40, 40);
g.fillRect(20, 90,40, 40);
g.fillRect(100, 90,40, 40);
g.fillRect(180, 90,40, 40);
g.fillRect(260, 90,40, 40);
g.fillRect(60, 130,40, 40);
g.fillRect(140, 130,40, 40);
g.fillRect(220, 130,40, 40);
g.fillRect(300, 130,40, 40);
g.fillRect(20, 170,40, 40);
g.fillRect(100, 170,40, 40);
g.fillRect(180, 170,40, 40);
g.fillRect(260, 170,40, 40);
g.fillRect(60, 210,40, 40);
g.fillRect(140, 210,40, 40);
g.fillRect(220, 210,40, 40);
g.fillRect(300, 210,40, 40);
g.fillRect(20, 250,40, 40);
g.fillRect(100, 250,40, 40);
g.fillRect(180, 250,40, 40);
g.fillRect(260, 250,40, 40);
g.fillRect(60, 290,40, 40);
g.fillRect(140, 290,40, 40);
g.fillRect(220, 290,40, 40);
g.fillRect(300, 290,40, 40);
}
easy