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里看一下,那样比较清晰 : )

posted on 2008-06-07 17:50  岚之山  阅读(202)  评论(0编辑  收藏  举报

导航