• Java中国象棋博弈程序探秘[3]——着法合法性判断


    着法合法性判断


    转载请保留作者信息:

    作者:88250

    Bloghttp:/blog.csdn.net/DL88250

    MSN & Gmail & QQDL88250@gmail.com

    本次,我们要着手于除了棋盘外——最基本着法合法性判断代码了。这些代码其实描述的是中国象棋的着法规则,玩过象棋的人应该很熟悉了,虽然比较繁琐,但是一定要写。而且,这一段代码对于性能的影响极大,是后面要介绍的着法生成与局面搜索的基础。


    好了,不多说了,直接贴代码了,里面注释很清楚了:

        /**
         * This method be used to determine the specified move is valid or not.
         * Firstly, let's glance at the <em>Chinese chess move rules</em>:
         * <p>
         * <h2>Jiang</h2>
         * <ol>
         *  <li>
         *      it can only move straight, the distance of one
         *      motion must equals to 1
         *  </li>
         *  <li>
         *      it can only move within the "Base".
         *  </li>
         *  <li>
         *      it can eat opponent's Jiang while nothing between them,
         *      and the "eatways" must be a line.
         *  </li>
         * </ol>
         * </p>
         * <p>
         * <h2>Shi</h2>
         * <ol>
         *  <li>
         *      it can only move to catercorner point of a square,
         *      that square's width equals to 1
         *  </li>
         *  <li>
         *      it can only move within the "Base". Refers to
         *      {@link Jiang#isValid(java.awt.Point)}
         *  </li>
         * </ol>
         * </p>
         * <p>
         * <h2>Xiang</h2>
         * <ol>
         *  <li>
         *      it can only move to catercorner point of a rectangle,
         *      that square's width equals to 2
         *  </li>
         *  <li>
         *      the aspect of this motion must has no chessman on the center of
         *      the square, no matter ours nor opponent's。The following example
         *      is invalid:<br>
         *      #---------<br>
         *      |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|
         *      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br>
         *      ----<b>&nbsp;&nbsp;X&nbsp;----</b><br>
         *      |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|
         *      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br>
         *      ---------Xiang
         *  </li>
         *  <li>
         *      a xiang can't move beyond our "He Jie"
         *  </li>
         * </ol>
         * </p>
         * <p>
         * <h2>Ma</h2>
         * <ol>
         *  <li>
         *      it can only move to catercorner point of a rectangle,
         *      that rectangle's width equals to 1, and height equals to
         *      2
         *  </li>
         *  <li>
         *      the aspect(the longger distance direction) of this motion
         *      must has no chessman , no matter ours nor opponent's。The
         *      following example is invalid:<br>
         *      #----<br>
         *      |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br>
         *      -----<b>X</b><br>
         *      |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br>
         *      -----Ma
         *  </li>
         * </ol>
         * </p>
         * <p>
         * <h2>Che</h2>
         * <ol>
         *  <li>it can only move straight</li>
         * </ol>
         * </p>
         * <p>
         * <h2>Pao</h2>
         * <ol>
         *  <li>
         *      it can only move straight
         *  </li>
         *  <li>
         *      it can eat opponent chessman between a chessman along a line,
         *      like this:<br>
         *      Pao----#------OpponentChessMan<br>
         *      <b>NOTE:</b> the motion only occur when eating
         *  </li>
         * </ol>
         * </p>
         * <p>
         * <h2>Bing</h2>
         * <ol>
         *  <li>it can move forward, no backward</li>
         *  <li>only when it passed the "Chu He Hang Jie",
         *       it can turn left/right forward</li>
         *  <li>motion distance equals 1</li>
         * </ol>
         * </p>
         * @param fromX x coordinate of a motion's start
         * @param fromY y coordinate of a motion's start
         * @param toX x coordinate of a motion's destination
         * @param toY y coordinate of a motion's destination
         * @return if is valid, returns <code>true</code>, otherwise,
         * returns <code>false</code>
         */
        final public boolean isValidMove(int fromX, int fromY, int toX, int toY) {
            if (basicMoveIsValid(fromX, fromY, toX, toY)) {
                int moveId = chessboard[fromX][fromY];
                int targetId = chessboard[toX][toY];

                switch (moveId) {
                    case 7:
                        //<editor-fold defaultstate="collapsed" desc="Hong Jiang">
                        if (toX < 3 || toX > 5) {
                            // violate the first rule
                            return false;
                        }

                        if (targetId == 14) {
                            int pivotCount = calcChessmanCountAlongLine(fromX, fromY,
                                                                        toX, toY);
                            if (pivotCount == 0) {
                                // the thrid rule
                                return true;
                            }
                        }

                        if (toY > 2) {
                            // violate the first rule
                            return false;
                        }

                        if (distanceSq(fromX, fromY, toX, toY) != 1) {
                            // violate the first rule
                            return false;
                        }
                        //</editor-fold>
                        break;
                    case 14:
                        //<editor-fold defaultstate="collapsed" desc="Hei Jiang">
                        if (toX < 3 || toX > 5) {
                            // violate the first rule
                            return false;
                        }

                        if (targetId == 7) {
                            int pivotCount = calcChessmanCountAlongLine(fromX, fromY,
                                                                        toX, toY);
                            if (pivotCount == 0) {
                                // the thrid rule
                                return true;
                            }
                        }

                        if (toY < 7) {
                            // violate the first rule
                            return false;
                        }

                        if (distanceSq(fromX, fromY, toX, toY) != 1) {
                            // violate the first rule
                            return false;
                        }
                        //</editor-fold>
                        break;
                    case 6:
                        //<editor-fold defaultstate="collapsed" desc="Hong Shi">
                        if (toX < 3 || toX > 5 || toY > 3) {
                            // violate the first rule
                            return false;
                        }

                        if (distanceSq(fromX, fromY, toX, toY) != 2) {
                            // violate the first rule
                            return false;
                        }
                        //</editor-fold>
                        break;
                    case 13:
                        //<editor-fold defaultstate="collapsed" desc="Hei Shi">
                        if (toX < 3 || toX > 5 || toY < 8) {
                            // violate the first rule
                            return false;
                        }

                        if (distanceSq(fromX, fromY, toX, toY) != 2) {
                            // violate the first rule
                            return false;
                        }



                        //</editor-fold>
                        break;
                    case 5:
                        //<editor-fold defaultstate="collapsed" desc="Hong Xiang">
                        if (toY > 4) {
                            return false;
                        }

                        if (distanceSq(fromX, fromY, toX, toY) != 8) {
                            // violate the first rule
                            return false;
                        }

                        if (chessboard[(fromX + toX) / 2][(fromY + toY) / 2] != 0) {
                            // can't move widthways, violates the second rule
                            return false;
                        }
                        //</editor-fold>
                        break;
                    case 12:
                        //<editor-fold defaultstate="collapsed" desc=" Hei Xiang">
                        if (toY < 6) {
                            return false;
                        }

                        if (distanceSq(fromX, fromY, toX, toY) != 8) {
                            // violate the first rule
                            return false;
                        }

                        if (chessboard[(fromX + toX) / 2][(fromY + toY) / 2] != 0) {
                            // can't move widthways, violates the second rule
                            return false;
                        }
                        //</editor-fold>
                        break;
                    case 2:
                    case 9:
                        //<editor-fold defaultstate="collapsed" desc="Ma">
                        if (distanceSq(fromX, fromY, toX, toY) != 5) {
                            // violate the first rule
                            return false;
                        }

                        if (chessboard[(fromX + toX) / 2][fromY] != 0 &&
                                abs(fromY - toY) == 1) {
                            // can't move widthways, violates the second rule
                            return false;
                        }

                        if (chessboard[fromX][(fromY + toY) / 2] != 0 &&
                                abs(fromX - toX) == 1) {
                            // can't move lengthways violates the second rule
                            return false;
                        }
                        //</editor-fold>
                        break;
                    case 1:
                    case 8:
                        //<editor-fold defaultstate="collapsed" desc="Che">
                        if (fromX != toX && fromY != toY) {
                            // must move straight
                            return false;
                        }

                        int pivotCount = calcChessmanCountAlongLine(fromX, fromY,
                                                                    toX, toY);
                        // move eat motion!
                        if (pivotCount != 0) {
                            return false;
                        }
                        //</editor-fold>
                        break;
                    case 3:
                    case 10:
                        //<editor-fold defaultstate="collapsed" desc="Pao">
                        if (fromX != toX && fromY != toY) {
                            // must move straight, violates the first rule
                            return false;
                        }

                        pivotCount = calcChessmanCountAlongLine(fromX, fromY,
                                                                toX, toY);

                        if (targetId != 0) {
                            // move eat motion!
                            if (pivotCount != 1) {
                                return false;
                            }
                        } else {
                            if (pivotCount != 0) {
                                return false;
                            }
                        }
                        //</editor-fold>
                        break;
                    case 4:
                    case 11:
                        //<editor-fold defaultstate="collapsed" desc="Bing">
                        if (fromX != toX && fromY != toY) {
                            // must move straight
                            return false;
                        }

                        if (distanceSq(fromX, fromY, toX, toY) != 1) {
                            // move forware ONLY ONE step
                            return false;
                        }

                        if (isBlack(moveId)) {
                            if (fromY > 4 && fromX != toX) {
                                // has nor yet passed the "He Jie"
                                // cannot turn left/right
                                return false;
                            }
                            if (fromY < toY) {
                                // "Bing" cannot backward!
                                return false;
                            }
                        } else {
                            if (fromY < 5 && fromX != toX) {
                                // has nor yet passed the "He Jie"
                                // cannot turn left/right
                                return false;
                            }
                            if (fromY > toY && fromX == toX) {
                                // "Bing" cannot backward!
                                return false;
                            }
                        }
                        //</editor-fold>
                        break;
                }
            } else {
                return false;
            }

            return true;
        }

    可以把代码贴到带Javadoc查看的IDE里看一下,那样比较清晰 : )

  • 相关阅读:
    html知识点
    BFC的布局规则以及触发条件
    父元素与子元素之间的margin-top问题(css hack)
    加overflow-hidden就可以解决高度塌陷问题,overflow-触发BFC
    子元素margin-top为何会影响父元素?
    子div设置margin-top使得父div也跟着向下移动
    vue 之 mongodb安装问题
    vue 之 nginx原理(webpack环境下配置)
    vue 之 PC端项目配置
    ASP.NET CORE (一)
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6470234.html
Copyright © 2020-2023  润新知