Java实现中国象棋的示例代码

网友投稿 230 2022-08-30


Java实现中国象棋的示例代码

目录前言主要设计功能截图代码实现总结

前言

中国象棋是起源于中国的一种棋,属于二人对抗性游戏的一种,在中国有着悠久的历史。由于用具简单,趣味性强,成为流行极为广泛的棋艺活动。

中国象棋使用方形格状棋盘,圆形棋子共有32个,红黑二色各有16个棋子,摆放和活动在交叉点上。双方交替行棋,先把对方的将(帅)“将死”的一方获胜。

中国象棋是一款具有浓郁中国特色的益智游戏,新增的联网对战,趣味多多,聚会可以约小朋友一起来挑战。精彩的对弈让你感受中国象棋的博大精深。

《中国象棋》游戏是用java语言实现,采用了swing技术进行了界面化处理,设计思路用了面向对象思想。, 人机对弈基于极大极小值搜索算法。

主要需求

按照中国象棋的规则,实现红黑棋对战,要有AI对手,可以玩家跟AI的对弈,也可以两个玩家自己玩。

主要设计

1、寻找棋盘界面和对应的棋子图片,程序设计棋盘界面和功能菜单

2、设计不同的棋子的移动逻辑

3、棋子移动时,要有音效

4、设计对手AI的逻辑算法,这里运用了极大极小值搜索算法,设置不同的搜索深度AI(智能不同)

5、对局开始前,双方棋子在棋盘上的摆法。

6、对局时,由执红棋的一方先走,双方轮流走一步。

7、轮到走棋的一方,将某个棋子从一个交叉点走到另一个交叉点,或者吃掉对方的棋子而占领其交叉点,都算走了一着。

8、双方各走一着,称为一个回合。

9、走一着棋时,如果己方棋子能够走到的位置有对方棋子存在,就可以把对方棋子吃掉而占领那个位置。

10、一方的棋子攻击对方的帅(将),并在下一着要把它吃掉,称为“照将”,或简称“将”。“照将”不必声明。被“照将”的一方必须立即“应将”,即用自己的着法去化解被“将”的状态。如果被“照将”而无法“应将”,就算被“将死”。

11、特别设计了人机对弈,人人对弈,还有AI对AI对弈

功能截图

游戏开始

游戏菜单设置

移动效果

代码实现

棋盘面板设计

@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 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 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);

}

}

命令执行器, 用于处理走棋中的命令

@Slf4j

public class CommandExecutor {

/**

* 异步调用线程, 来处理走棋命令

*/

private final CtrlLoopThreadComp ctrlLoopThreadComp;

private final BoardPanel boardPanel;

/**

* 是否持续运行标记

*/

private volatile boolean sustain;

public CommandExecutor(BoardPanel boardPanel) {

this.boardPanel = boardPanel;

this.ctrlLoopThreadComp = CtrlLoopThreadComp.ofRunnable(this::loop)

.setName("CommandExecutor")

.catchFun(CtrlLoopThreadComp.CATCH_FUNCTION_CONTINUE);

}

/**

* 下一步骤命令

*/

private CommandType nextCommand;

/**

* 下一步骤命令的参数

*/

private Object nextParamObj;

private volatile boolean isRun;

/**

* @param commandType 命令类型

*/

public void sendCommand(@NonNull CommandType commandType) {

sendCommand(commandType, null);

}

/**

* @param commandType 命令类型

* @param paramObj 命令参数

*/

public synchronized void sendCommand(@NonNull CommandType commandType, Object paramObj) {

this.nextCommand = commandType;

this.nextParamObj = paramObj;

sustain = false;

this.ctrlLoopThreadComp.startOrWake();

}

/**

* 只有在 线程没有运行的情况下, 才能添加成功

*

* @param commandType 命令类型

* @param paramObj 命令参数

* @return 是否添加成功

*/

public synchronized boolean sendCommandWhenNotRun(@NonNull CommandType commandType, Object paramObj) {

if (isRun) {

return false;

}

sendCommand(commandType, paramObj);

return true;

}

private void loop() {

final CommandType command;

final Object paramObj;

synchronized (this) {

command = this.nextCommand;

paramObj = this.nextParamObj;

this.nextCommand = null;

this.nextParamObj = null;

}

if (command != null) {

isRun = true;

try {

log.debug("处理事件[{}] start", command.getLabel());

consumerCommand(command, paramObj);

log.debug("处理事件[{}] end ", command.getLabel());

} catch (Exception e) {

log.error("执行命令[{}]发生异常", command.getLabel(), e);

new Thread(() -> JOptionPane.showMessageDialog(boardPanel, e.getMessage(), e.toString(), JOptionPane.ERROR_MESSAGE)).start();

}

} else {

this.ctrlLoopThreadComp.pause();

isRun = false;

}

}

/**

* 运行

*/

private void consumerCommand(final CommandType commandType, Object paramObj) {

switch (commandType) {

case SuspendCallBackOrAiRun:

break;

case CallBackOneTime:

Application.context().rollbackOneStep();

break;

case AiRunOneTime:

if (Application.context().aiRunOneTime() != null) {

log.debug("已经决出胜方!");

}

break;

case SustainCallBack:

sustain = true;

while (sustain) {

if (!Application.context().rollbackOneStep()) {

sustain = false;

break;

}

Throws.con(Application.config().getComIntervalTime(), Thread::sleep).logThrowable();

}

break;

case SustainAiRun:

sustain = true;

while (sustain) {

if (Application.context().aiRunOneTime() != null) {

log.debug("已经决出胜方, AI执行暂停!");

sustain = false;

break;

}

Throws.con(Application.config().getComIntervalTime(), Thread::sleep).logThrowable();

}

break;

case SustainAiRunIfNextIsAi:

sustain = true;

while (sustain) {

// 如果下一步棋手不是 AI, 则暂停

if (!PlayerType.COM.equals(Application.config().getPlayerType(Application.context().getSituation().getNextPart()))) {

sustain = false;

log.debug("下一步棋手不是 AI, 暂停!");

} else if (Application.context().aiRunOneTime() != null) {

log.debug("已经决出胜方, AI执行暂停!");

sustain = false;

} else {

Throws.con(Application.config().getComIntervalTime(), Thread::sleep).logThrowable();

}

}

break;

case LocationPiece:

final Object[] params = (Object[]) paramObj;

Place from = (Place) params[0];

Place to = (Place) params[1];

PlayerType type = (PlayerType) params[2];

Application.context().locatePiece(from, to, type);

sendCommand(CommandExecutor.CommandType.SustainAiRunIfNextIsAi);

break;

default:

throw new ShouldNotHappenException("未处理的命令: " + commandType);

}

}

/**

* 命令支持枚举(以下命令应当使用同一个线程运行, 一个事件结束之后, 另一个事件才能开始运行.)

*/

@SuppressWarnings("java:S115")

public enum CommandType {

SuspendCallBackOrAiRun("停止撤销|AI计算"),

CallBackOneTime("撤销一步"),

SustainCallBack("持续撤销"),

AiRunOneTime("AI计算一步"),

SustainAiRun("AI持续运行"),

SustainAiRunIfNextIsAi("COM角色运行"),

LocationPiece("ui落子命令");

@Getter

private final String label;

CommandType(String label) {

this.label = label;

}

}

}

核心算法

@NoArgsConstructor(access = AccessLevel.PRIVATE)

@Slf4j

public class AlphaBeta {

private static final int MAX = 100_000_000;

/**

* 这里要保证 Min + Max = 0, 哪怕是微不足道的差距都可能导致发生错误

*/

private static final int MIN = -MAX;

/**

* 根据棋子数量, 动态调整搜索深度

*

* @param pieceNum 棋子数量

* @return 调整搜索深度差值

*/

public static int searchDeepSuit(final int pieceNum) {

// 根据棋子数量, 动态调整搜索深度

if (pieceNum > 20) {

return -2;

} else if (pieceNum <= 4) {

return 4;

} else if (pieceNum <= 8) {

return 2;

}

return 0;

}

/**

* 生成待选的列表,就是可以下子的空位, 如果 deep > 2 则对搜索结果进行排序.

*

* @param analysisBean 棋盘分析对象

* @param curPart 当前走棋方

* @param deep 搜索深度

* @return 可以下子的空位集合

*/

private static MyList geneNestStepPlaces(final AnalysisBean analysisBean, final Part curPart, final int deep) {

final Piece[][] pieces = analysisBean.pieces;

// 是否杀棋

MyList stepBeanList = ListPool.localPool().getAStepBeanList();

for (int x = 0; x < ChessDefined.RANGE_X; x++) {

for (int y = 0; y < ChessDefined.RANGE_Y; y++) {

final Piece fromPiece = pieces[x][y];

if (fromPiece != null && fromPiece.part == curPart) {

final Place from = Place.of(x, y);

// TO DO 考虑下此处添加至集合的做法 在计算时 是否有优化空间.

final MyList list = fromPiece.role.find(analysisBean, curPart, from);

if (list.isEmpty()) {

ListPool.localPool().addListToPool(list);

continue;

}

final Object[] elementData = list.eleTemplateDate();

for (int i = 0, len = list.size(); i < len; i++) {

stepBeanList.add(StepBean.of(from, (Place) elementData[i]));

}

ListPool.localPool().addListToPool(list);

}

}

}

// 是否排序, 如果搜索深度大于2, 则对结果进行排序

// 排序后的结果, 进入极大极小值搜索算法时, 容易被剪枝.

if (deep > 2) {

orderStep(analysisBean, stepBeanList, curPart);

}

return stepBeanList;

}

/**

* 对 空位列表 进行排序, 排序后的空位列表, 进入极大极小值搜索算法时, 容易被剪枝.

*

* @param analysisBean 棋盘分析对象

* @param stepBeanList 可以下子的空位列表

* @param curPart 当前走棋方

*/

private static void orderStep(final AnalysisBean analysisBean, final MyList stepBeanList, final Part curPart) {

final Piece[][] srcPieces = analysisBean.pieces;

// 进入循环之前计算好循环内使用常量

MyList> bestPlace = ListPool.localPool().getADoubleBeanList();

// 对方棋手

final Part oppositeCurPart = Part.getOpposite(curPart);

int best = MIN;

final Object[] objects = stepBeanList.eleTemplateDate();

for (int i = 0; i < stepBeanList.size(); i++) {

final StepBean item = (StepBean) objects[i];

final Place to = item.to;

// 备份

final Piece eatenPiece = srcPieces[to.x][to.y];

int score;

// 判断是否胜利

if (eatenPiece != null && eatenPiece.role == Role.BOSS) {

score = MAX;

} else {

// 走棋

final int invScr = analysisBean.goForward(item.from, to, eatenPiece);

DebugInfo.incrementAlphaBetaOrderTime();

// 评分

score = negativeMaximumWithNoCut(analysisBean, oppositeCurPart, -best);

// 退回上一步

analysisBean.backStep(item.from, to, eatenPiece, invScr);

}

// 这里添加进所有的分数

bestPlace.add(new DoubleBean<>(score, item));

if (score > best) { // 找到一个更好的分,就把以前存的位子全部清除

best = score;

}

}

/* 排序后返回 */

// 这样排序是正确的, 可以有效消减数量

bestPlace.sort((o1, o2) -> o2.getO1() - o1.getO1());

stepBeanList.clear();

bestPlace.forEach(dou -> stepBeanList.add(dou.getO2()));

ListPool.localPool().addListToDoubleBeanListPool(bestPlace);

}

/**

* 负极大值搜索算法(不带剪枝算法)

*

* @param analysisBean 局势分析对象

* @param curPart 当前走棋方

* @return 负极大值搜索算法计算分值

*/

private static int negativeMaximumWithNoCut(AnalysisBean analysisBean, Part curPart, int alphaBeta) {

// 1. 初始化各个变量

final Piece[][] pieces = analysisBean.pieces;

int best = MIN;

// 2. 生成待选的列表,就是可以下子的列表

MyList stepBeanList = geneNestStepPlaces(analysisBean, curPart, 1);

final Object[] objects = stepBeanList.eleTemplateDate();

for (int i = 0, len = stepBeanList.size(); i < len; i++) {

final StepBean item = (StepBean) objects[i];

Place from = item.from;

Place to = item.to;

// 备份

Piece eatenPiece = pieces[to.x][to.y];

int score;

// 判断是否胜利

if (eatenPiece != null && eatenPiece.role == Role.BOSS) {

score = MAX;

} else {

// 走棋

final int invScr = analysisBean.goForward(from, to, eatenPiece);

DebugInfo.incrementAlphaBetaOrderTime();

score = analysisBean.getCurPartEvaluateScore(curPart);

// 退回上一步

analysisBean.backStep(from, to, eatenPiece, invScr);

}

if (score > best) { // 找到一个更好的分,就更新分数

best = score;

}

if (score > alphaBeta) { // alpha剪枝

break;

}

}

ListPool.localPool().addListToStepBeanListPool(stepBeanList);

return -best;

}

/**

* 奇数层是电脑(max层)thisSide, 偶数层是human(min层)otherSide

*

* @param srcPieces 棋盘

* @param curPart 当前走棋方

* @param deep 搜索深度

* @param forbidStep 禁止的步骤(长捉或长拦)

* @return 下一步的位置

*/

public static Set getEvaluatedPlace(final Piece[][] srcPieces, final Part curPart, final int deep, final StepBean forbidStep) {

// 1. 初始化各个变量

final AnalysisBean analysisBean = new AnalysisBean(srcPieces);

// 2. 获取可以下子的空位列表

MyList stepBeanList = geneNestStepPlaces(analysisBean, curPart, deep);

// 3. 移除不该下的子

stepBeanList.remove(forbidStep);

// 进入循环之前计算好循环内使用常量

Set bestPlace = new HashSet<>();

int best = MIN;

// 对方棋手

final Part oppositeCurPart = Part.getOpposite(curPart);

// 下一深度

final int nextDeep = deep - 1;

log.debug("size : {}, content: {}", stepBeanList.size(), stepBeanList);

final Object[] objects = stepBeanList.eleTemplateDate();

for (int i = 0, len = stepBeanList.size(); i < len; i++) {

StepBean item = (StepBean) objects[i];

final Place to = item.to;

// 备份

final Piece eatenPiece = srcPieces[to.x][to.y];

int score;

// 判断是否胜利

if (eatenPiece != null && eatenPiece.role == Role.BOSS) {

// 步数越少, 分值越大

score = MAX + deep;

} else {

// 走棋

final int invScr = analysisBean.goForward(item.from, to, eatenPiece);

// 评分

if (deep <= 1) {

score = analysisBean.getCurPartEvaluateScore(curPart);

} else {

score = negativeMaximum(analysisBean, oppositeCurPart, nextDeep, -best);

}

http:// // 退回上一步

analysisBean.backStep(item.from, to, eatenPiece, invScr);

}

if (score == best) { // 找到相同的分数, 就添加这一步

bestPlace.add(item);

}

if (score > best) { // 找到一个更好的分,就把以前存的位子全部清除

best = score;

bestPlace.clear();

bestPlace.add(item);

}

}

ListPool.end();

ListPool.localPool().addListToStepBeanListPool(stepBeanList);

return bestPlace;

}

/**

* 奇数层是电脑(max层)thisSide, 偶数层是human(min层)otherSide

*

* @param srcPieces 棋盘

* @param curPart 当前走棋方

* @param deep 搜索深度

* @param forbidStep 禁止的步骤(长捉或长拦)

* @return 下一步的位置

*/

public static Set getEvaluatedPlaceWithParallel(final Piece[][] srcPieces, final Part curPart, final http://int deep, final StepBean forbidStep) {

// 1. 初始化各个变量

final AnalysisBean srcAnalysisBean = new AnalysisBean(srcPieces);

// 2. 获取可以下子的空位列表

MyList stepBeanList = geneNestStepPlaces(srcAnalysisBean, curPart, deep);

// 3. 移除不该下的子

stepBeanList.remove(forbidStep);

// 进入循环之前计算好循环内使用常量

final Set bestPlace = new HashSet<>();

final AtomicInteger best = new AtomicInteger(MIN);

// 对方棋手

final Part oppositeCurPart = Part.getOpposite(curPart);

// 下一深度

final int nextDeep = deep - 1;

log.debug("size : {}, content: {}", stepBeanList.size(), stepBeanList);

Arrays.stream(stepBeanList.toArray()).parallel().filter(Objects::nonNull).map(StepBean.class::cast).forEach(item -> {

log.debug("并行流 ==> Thread : {}", Thread.currentThread().getId());

final Piece[][] pieces = ArrayUtils.deepClone(srcPieces);

final AnalysisBean analysisBean = new AnalysisBean(pieces);

final Place to = item.to;

// 备份

final Piece eatenPiece = pieces[to.x][to.y];

int score;

// 判断是否胜利

if (eatenPiece != null && eatenPiece.role == Role.BOSS) {

// 步数越少, 分值越大

score = MAX + deep;

} else {

// 走棋

final int invScr = analysisBean.goForward(item.from, to, eatenPiece);

// 评分

if (deep <= 1) {

score = analysisBean.getCurPartEvaluateScore(curPart);

} else {

score = negativeMaximum(analysisBean, oppositeCurPart, nextDeep, -best.get());

}

// 退回上一步

analysisBean.backStep(item.from, to, eatenPiece, invScr);

}

if (score == best.get()) { // 找到相同的分数, 就添加这一步

synchronized (bestPlace) {

bestPlace.add(item);

}

}

if (score > best.get()) { // 找到一个更好的分,就把以前存的位子全部清除

best.set(score);

synchronized (bestPlace) {

bestPlace.clear();

bestPlace.add(item);

}

}

ListPool.end();

});

ListPool.localPool().addListToStepBeanListPool(stepBeanList);

ListPool.end();

return bestPlace;

}

/**

* 负极大值搜索算法

*

* @param analysisBean 局势分析对象

* @param curPart 当前走棋方

* @param deep 搜索深度

* @param alphaBeta alphaBeta 剪枝分值

* @return 负极大值搜索算法计算分值

*/

private static int negativeMaximum(AnalysisBean analysisBean, Part curPart, int deep, int alphaBeta) {

// 1. 初始化各个变量

final Piece[][] pieces = analysisBean.pieces;

int best = MIN;

// 对方棋手

final Part oppositeCurPart = Part.getOpposite(curPart);

// 下一深度

final int nextDeep = deep - 1;

// 2. 生成待选的列表,就是可以下子的列表

final MyList stepBeanList = geneNestStepPlaces(analysisBean, curPart, deep);

final Object[] objects = stepBeanList.eleTemplateDate();

for (int i = 0, len = stepBeanList.size(); i < len; i++) {

final StepBean item = (StepBean) objects[i];

Place from = item.from;

Place to = item.to;

// 备份

Piece eatenPiece = pieces[to.x][to.y];

int score;

// 判断是否胜利

if (eatenPiece != null && eatenPiece.role == Role.BOSS) {

// 步数越少, 分值越大

score = MAX + deep;

} else {

// 走棋

final int invScr = analysisBean.goForward(from, to, eatenPiece);

// 评估

if (deep <= 1) {

score = analysisBean.getCurPartEvaluateScore(curPart);

} else {

score = negativeMaximum(analysisBean, oppositeCurPart, nextDeep, -best);

}

// 退回上一步

analysisBean.backStep(from, to, eatenPiece, invScr);

}

if (score > best) { // 找到一个更好的分,就更新分数

best = score;

}

if (score > alphaBeta) { // alpha剪枝

break;

}

}

ListPool.localPool().addListToStepBeanListPool(stepBeanList);

return -best;

}

}

总结

通过此次的《中国象棋》游戏实现,让我对swing的相关知识有了进一步的了解,对java这门语言也有了比以前更深刻的认识。

java的一些基本语法,比如数据类型、运算符、程序流程控制和数组等,理解更加透彻。java最核心的核心就是面向对象思想,对于这一个概念,终于悟到了一些。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:制作Python Egg, 上传PyPI 转载:https://www.xiaoh.me/2015/12/11/python-egg/(制作python库)
下一篇:pandas IO(pandas什么意思)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~