您目前所在位置: 首页 > 游戏周边 > 新手帮助

中国象棋人机对战下载安装(程序编写的象棋人机对战游戏)

时间:2022-07-03 10:59:06 | 访问:86 次 | 责任编辑:访客

前言

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

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

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

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

主要需求

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

主要设计

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

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

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

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

5、对局开始前,双方棋子在棋盘上的摆法。 6、对局时,由执红棋的一方先走,双方轮流走一步。 7、轮到走棋的一方,将某个棋子从一个交叉点走到另一个交叉点,或者吃掉对方的棋子而占领其交叉点,都算走了一着。 8、双方各走一着,称为一个回合。 9、走一着棋时,如果己方棋子能够走到的位置有对方棋子存在,就可以把对方棋子吃掉而占领那个位置。 10、一方的棋子攻击对方的帅(将),并在下一着要把它吃掉,称为“照将”,或简称“将”。“照将”不必声明。被“照将”的一方必须立即“应将”,即用自己的着法去化解被“将”的状态。如果被“照将”而无法“应将”,就算被“将死”。

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

功能截图

游戏开始

JAVA实现经典《中国象棋》游戏

游戏菜单设置

JAVA实现经典《中国象棋》游戏

移动效果

JAVA实现经典《中国象棋》游戏

代码实现

棋盘面板设计

@Slf4j publicclassBoardPanelextendsJPanelimplementsLambdaMouseListener{/** * 用于标记棋盘走棋痕迹 */privatefinaltransient TraceMarker traceMarker; /** * 当前走棋开始坐标位置对应棋子 */privatetransient ChessPiece curFromPiece; /** * 场景 */privatetransient Situation situation; /** * Create the panel. */publicBoardPanel(){ setBorder(newEmptyBorder(5, 5, 5, 5)); setLayout(null); // 初始化标记符traceMarker = newTraceMarker(BoardPanel.this); // 添加鼠标事件addMouseListener(this); } /** * 更新标记 */publicvoidupdateMark(Place from, Place to){ // 更新标记curFromPiece = null; // 更改标记traceMarker.endedStep(from, to); } /** * 初始化所有标记 */publicvoidinitMark(){ traceMarker.initMarker(); } /** * 添加棋子 */publicvoidinit(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 publicvoidmouseReleased(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: formif(curFromPiece == null) { // 当前焦点位置有棋子且是本方棋子if(pointerPiece != null && pointerPiece.piece.part == pointerPart) { // 本方棋子, 同时是from指向curFromPiece = pointerPiece; traceMarker.setMarkFromPlace(pointerPlace); // 获取toListMyList<Place> list= curFromPiece.piece.role.find(newAnalysisBean(situation.generatePieces()), pointerPart, pointerPlace); traceMarker.showMarkPlace(list); ChessAudio.CLICK_FROM.play(); log.info("true -> 当前焦点位置有棋子且是本方棋子"); finalListPool 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 : "当前焦点位置有棋子且是本方棋子 之前指向了对方棋子"; // 更新 curFromPiececurFromPiece = pointerPiece; traceMarker.setMarkFromPlace(pointerPlace); MyList<Place> list= curFromPiece.piece.role.find(newAnalysisBean(situation.generatePieces()), pointerPart, pointerPlace); traceMarker.showMarkPlace(list); ChessAudio.CLICK_FROM.play(); log.info("true -> 更新 curFromPiece"); ListPool.localPool().addListToPool(list); return; } finalStepBean stepBean = StepBean.of(curFromPiece.getPlace(), pointerPlace); // 如果不符合规则则直接返回finalPiece[][] pieces = situation.generatePieces(); if(!curFromPiece.piece.role.rule.check(pieces, pointerPart, stepBean.from, stepBean.to)) { // 如果当前指向棋子是本方棋子log.warn("不符合走棋规则"); return; } // 如果达成长拦或者长捉, 则返回finalStepBean forbidStepBean = situation.getForbidStepBean(); if(forbidStepBean != null && forbidStepBean.from == stepBean.from && forbidStepBean.to == stepBean.to) { ChessAudio.MAN_MOV_ERROR.play(); log.warn("长拦或长捉"); return; } AnalysisBean analysisBean = newAnalysisBean(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 = newObject[]{stepBean.from, stepBean.to, PlayerType.PEOPLE}; finalboolean sendSuccess = Application.context().getCommandExecutor().sendCommandWhenNotRun(CommandExecutor.CommandType.LocationPiece, objects); if(!sendSuccess) { log.warn("命令未发送成功: {} ==> {}", CommandExecutor.CommandType.LocationPiece, Arrays.toString(objects)); } } @Override publicvoidpaintComponent(Graphics g){ super.paintComponent(g); Image img = ChessImage.CHESS_BOARD.getImage(); intimgWidth = img.getWidth(this); intimgHeight = img.getHeight(this);// 获得图片的宽度与高度intfWidth = getWidth(); intfHeight = getHeight();// 获得窗口的宽度与高度intx = (fWidth - imgWidth) / 2; inty = (fHeight - imgHeight) / 2; // 520 576 514 567log.debug(String.format("%s,%s,%s,%s,%s,%s", imgWidth, imgHeight, fWidth, fHeight, x, y)); g.drawImage(img, 0, 0, null); } } 复制代码

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

@Slf4jpublicclassCommandExecutor{ /** * 异步调用线程, 来处理走棋命令 */privatefinalCtrlLoopThreadComp ctrlLoopThreadComp; privatefinalBoardPanel boardPanel; /** * 是否持续运行标记 */privatevolatileboolean sustain; publicCommandExecutor(BoardPanel boardPanel) { this.boardPanel = boardPanel; this.ctrlLoopThreadComp = CtrlLoopThreadComp.ofRunnable(this::loop) .setName("CommandExecutor") .catchFun(CtrlLoopThreadComp.CATCH_FUNCTION_CONTINUE); } /** * 下一步骤命令 */privateCommandType nextCommand; /** * 下一步骤命令的参数 */privateObject nextParamObj; privatevolatileboolean isRun; /** * @paramcommandType 命令类型 */publicvoid sendCommand(@NonNullCommandType commandType) { sendCommand(commandType, null); } /** * @paramcommandType 命令类型 * @paramparamObj 命令参数 */publicsynchronized void sendCommand(@NonNullCommandType commandType, Object paramObj) { this.nextCommand = commandType; this.nextParamObj = paramObj; sustain = false; this.ctrlLoopThreadComp.startOrWake(); } /** * 只有在 线程没有运行的情况下, 才能添加成功 * * @paramcommandType 命令类型 * @paramparamObj 命令参数 * @return是否添加成功 */publicsynchronized boolean sendCommandWhenNotRun(@NonNullCommandType commandType, Object paramObj) { if(isRun) { returnfalse; } sendCommand(commandType, paramObj); returntrue; } privatevoid loop() { finalCommandType command; finalObject 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; } } /** * 运行 */privatevoid consumerCommand(finalCommandType 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, 暂停!"); } elseif(Application.context().aiRunOneTime() != null) { log.debug("已经决出胜方, AI执行暂停!"); sustain = false; } else{ Throws.con(Application.config().getComIntervalTime(), Thread::sleep).logThrowable(); } } break; case LocationPiece: finalObject[] 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: thrownew ShouldNotHappenException("未处理的命令: "+ commandType); } } /** * 命令支持枚举(以下命令应当使用同一个线程运行, 一个事件结束之后, 另一个事件才能开始运行.) */@SuppressWarnings("java:S115")publicenumCommandType { SuspendCallBackOrAiRun("停止撤销|AI计算"), CallBackOneTime("撤销一步"), SustainCallBack("持续撤销"), AiRunOneTime("AI计算一步"), SustainAiRun("AI持续运行"), SustainAiRunIfNextIsAi("COM角色运行"), LocationPiece("ui落子命令"); @GetterprivatefinalString label; CommandType(String label) { this.label = label; } } } 复制代码

核心算法

@NoArgsConstructor(access = AccessLevel.PRIVATE) @Slf4j publicclassAlphaBeta{privatestaticfinalintMAX = 100_000_000; /** * 这里要保证 Min + Max = 0, 哪怕是微不足道的差距都可能导致发生错误 */privatestaticfinalintMIN = -MAX; /** * 根据棋子数量, 动态调整搜索深度 * * @param pieceNum 棋子数量 * @return 调整搜索深度差值 */publicstaticintsearchDeepSuit(finalintpieceNum){ // 根据棋子数量, 动态调整搜索深度if(pieceNum > 20) { return-2; } elseif(pieceNum <= 4) { return4; } elseif(pieceNum <= 8) { return2; } return0; } /** * 生成待选的列表,就是可以下子的空位, 如果 deep > 2 则对搜索结果进行排序. * * @param analysisBean 棋盘分析对象 * @param curPart 当前走棋方 * @param deep 搜索深度 * @return 可以下子的空位集合 */privatestaticMyList<StepBean> geneNestStepPlaces(finalAnalysisBean analysisBean, finalPart curPart, finalintdeep) { finalPiece[][] pieces = analysisBean.pieces; // 是否杀棋MyList<StepBean> stepBeanList = ListPool.localPool().getAStepBeanList(); for(intx = 0; x < ChessDefined.RANGE_X; x++) { for(inty = 0; y < ChessDefined.RANGE_Y; y++) { finalPiece fromPiece = pieces[x][y]; if(fromPiece != null && fromPiece.part == curPart) { finalPlace from = Place.of(x, y); // TO DO 考虑下此处添加至集合的做法 在计算时 是否有优化空间.finalMyList<Place> list= fromPiece.role.find(analysisBean, curPart, from); if(list.isEmpty()) { ListPool.localPool().addListToPool(list); continue; } finalObject[] elementData = list.eleTemplateDate(); for(inti = 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); } returnstepBeanList; } /** * 对 空位列表 进行排序, 排序后的空位列表, 进入极大极小值搜索算法时, 容易被剪枝. * * @param analysisBean 棋盘分析对象 * @param stepBeanList 可以下子的空位列表 * @param curPart 当前走棋方 */privatestaticvoidorderStep(finalAnalysisBean analysisBean, finalMyList<StepBean> stepBeanList, finalPart curPart){ finalPiece[][] srcPieces = analysisBean.pieces; // 进入循环之前计算好循环内使用常量MyList<DoubleBean<Integer, StepBean>> bestPlace = ListPool.localPool().getADoubleBeanList(); // 对方棋手finalPart oppositeCurPart = Part.getOpposite(curPart); intbest = MIN; finalObject[] objects = stepBeanList.eleTemplateDate(); for(inti = 0; i < stepBeanList.size(); i++) { finalStepBean item = (StepBean) objects[i]; finalPlace to = item.to; // 备份finalPiece eatenPiece = srcPieces[to.x][to.y]; intscore; // 判断是否胜利if(eatenPiece != null && eatenPiece.role == Role.BOSS) { score = MAX; } else{ // 走棋finalintinvScr = analysisBean.goForward(item.from, to, eatenPiece); DebugInfo.incrementAlphaBetaOrderTime(); // 评分score = negativeMaximumWithNoCut(analysisBean, oppositeCurPart, -best); // 退回上一步analysisBean.backStep(item.from, to, eatenPiece, invScr); } // 这里添加进所有的分数bestPlace.add(newDoubleBean<>(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 负极大值搜索算法计算分值 */privatestaticintnegativeMaximumWithNoCut(AnalysisBean analysisBean, Part curPart, intalphaBeta){ // 1. 初始化各个变量finalPiece[][] pieces = analysisBean.pieces; intbest = MIN; // 2. 生成待选的列表,就是可以下子的列表MyList<StepBean> stepBeanList = geneNestStepPlaces(analysisBean, curPart, 1); finalObject[] objects = stepBeanList.eleTemplateDate(); for(inti = 0, len = stepBeanList.size(); i < len; i++) { finalStepBean item = (StepBean) objects[i]; Place from = item.from; Place to = item.to; // 备份Piece eatenPiece = pieces[to.x][to.y]; intscore; // 判断是否胜利if(eatenPiece != null && eatenPiece.role == Role.BOSS) { score = MAX; } else{ // 走棋finalintinvScr = 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 下一步的位置 */publicstaticSet<StepBean> getEvaluatedPlace(finalPiece[][] srcPieces, finalPart curPart, finalintdeep, finalStepBean forbidStep) { // 1. 初始化各个变量finalAnalysisBean analysisBean = newAnalysisBean(srcPieces); // 2. 获取可以下子的空位列表MyList<StepBean> stepBeanList = geneNestStepPlaces(analysisBean, curPart, deep); // 3. 移除不该下的子stepBeanList.remove(forbidStep); // 进入循环之前计算好循环内使用常量Set<StepBean> bestPlace = newHashSet<>(); intbest = MIN; // 对方棋手finalPart oppositeCurPart = Part.getOpposite(curPart); // 下一深度finalintnextDeep = deep - 1; log.debug("size : {}, content: {}", stepBeanList.size(), stepBeanList); finalObject[] objects = stepBeanList.eleTemplateDate(); for(inti = 0, len = stepBeanList.size(); i < len; i++) { StepBean item = (StepBean) objects[i]; finalPlace to = item.to; // 备份finalPiece eatenPiece = srcPieces[to.x][to.y]; intscore; // 判断是否胜利if(eatenPiece != null && eatenPiece.role == Role.BOSS) { // 步数越少, 分值越大score = MAX + deep; } else{ // 走棋finalintinvScr = analysisBean.goForward(item.from, to, eatenPiece); // 评分if(deep <= 1) { score = analysisBean.getCurPartEvaluateScore(curPart); } else{ score = negativeMaximum(analysisBean, oppositeCurPart, nextDeep, -best); } // 退回上一步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); returnbestPlace; } /** * 奇数层是电脑(max层)thisSide, 偶数层是human(min层)otherSide * * @param srcPieces 棋盘 * @param curPart 当前走棋方 * @param deep 搜索深度 * @param forbidStep 禁止的步骤(长捉或长拦) * @return 下一步的位置 */publicstaticSet<StepBean> getEvaluatedPlaceWithParallel(finalPiece[][] srcPieces, finalPart curPart, finalintdeep, finalStepBean forbidStep) { // 1. 初始化各个变量finalAnalysisBean srcAnalysisBean = newAnalysisBean(srcPieces); // 2. 获取可以下子的空位列表MyList<StepBean> stepBeanList = geneNestStepPlaces(srcAnalysisBean, curPart, deep); // 3. 移除不该下的子stepBeanList.remove(forbidStep); // 进入循环之前计算好循环内使用常量finalSet<StepBean> bestPlace = newHashSet<>(); finalAtomicInteger best = newAtomicInteger(MIN); // 对方棋手finalPart oppositeCurPart = Part.getOpposite(curPart); // 下一深度finalintnextDeep = 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()); finalPiece[][] pieces = ArrayUtils.deepClone(srcPieces); finalAnalysisBean analysisBean = newAnalysisBean(pieces); finalPlace to = item.to; // 备份finalPiece eatenPiece = pieces[to.x][to.y]; intscore; // 判断是否胜利if(eatenPiece != null && eatenPiece.role == Role.BOSS) { // 步数越少, 分值越大score = MAX + deep; } else{ // 走棋finalintinvScr = 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(); returnbestPlace; } /** * 负极大值搜索算法 * * @param analysisBean 局势分析对象 * @param curPart 当前走棋方 * @param deep 搜索深度 * @param alphaBeta alphaBeta 剪枝分值 * @return 负极大值搜索算法计算分值 */privatestaticintnegativeMaximum(AnalysisBean analysisBean, Part curPart, intdeep, intalphaBeta){ // 1. 初始化各个变量finalPiece[][] pieces = analysisBean.pieces; intbest = MIN; // 对方棋手finalPart oppositeCurPart = Part.getOpposite(curPart); // 下一深度finalintnextDeep = deep - 1; // 2. 生成待选的列表,就是可以下子的列表finalMyList<StepBean> stepBeanList = geneNestStepPlaces(analysisBean, curPart, deep); finalObject[] objects = stepBeanList.eleTemplateDate(); for(inti = 0, len = stepBeanList.size(); i < len; i++) { finalStepBean item = (StepBean) objects[i]; Place from = item.from; Place to = item.to; // 备份Piece eatenPiece = pieces[to.x][to.y]; intscore; // 判断是否胜利if(eatenPiece != null && eatenPiece.role == Role.BOSS) { // 步数越少, 分值越大score = MAX + deep; } else{ // 走棋finalintinvScr = 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最核心的核心就是面向对象思想,对于这一个概念,终于悟到了一些。


本类TOP10
最新内容
金融习题 考研百科