空当接龙求解:java版广度优先

说是广度优先,其实一搜到底还是不可能的,通过多少步(比如30万的节点)扩展后,选取一个最合适的节点(倒数第四层节点的第4层孙节点数量最多的那个),重新进行同样步骤,直到扩展节点出现终局节点为止,system.out.print输出解局过程

图片是解局过程片段

package kdjl3;
import java.util.ArrayList;
import java.util.HashMap;

public class Kdjl {

    public static void main(String[] args){
        Kdjl kdjl=new Kdjl();
        CurData curDataRoot = kdjl.getNewGame();
        //kdjl.exchangeCol(curDataRoot, 3, 7);
        kdjl.freecell(curDataRoot);
        /*
        System.out.println("DEBUG FOR MEMORY RELEASE CHECK.");
        kdjl=null;
        kdjl=new Kdjl();
        kdjl.freecell();
        System.out.println("DEBUG FOR MEMORY RELEASE CHECK.");
        kdjl.freecell();
        kdjl.freecell();
        kdjl.freecell();
        kdjl.freecell();
        kdjl.freecell();
        kdjl.freecell();
        kdjl.freecell();
        */
    }
    
    void exchangeCol(CurData cData,int c1,int c2) {
        int[] iTmp = new int[8];
        int backupCol,ppCol,iTmpBp;
        if(cData.bp[c1]>cData.bp[c2]) { backupCol = c1; ppCol = c2;}
        else { backupCol = c2; ppCol=c1;}
        for(int i=0;i<cData.bp[backupCol];i++) iTmp[i] = cData.board[backupCol][i];
        for(int i=0;i<cData.bp[ppCol];i++) cData.board[backupCol][i] = cData.board[ppCol][i];
        for(int i=0;i<cData.bp[backupCol];i++) cData.board[ppCol][i] = iTmp[i];
        iTmpBp=cData.bp[backupCol];
        cData.bp[backupCol]=cData.bp[ppCol];
        cData.bp[ppCol]=iTmpBp;
    }
    
    public CurData getNewGame() {
        CurData curDataRoot= new CurData();
        curDataRoot.bp[0] = 7;
        curDataRoot.bp[1] = 7;
        curDataRoot.bp[2] = 7;
        curDataRoot.bp[3] = 7;
        curDataRoot.bp[4] = 6;
        curDataRoot.bp[5] = 6;
        curDataRoot.bp[6] = 6;
        curDataRoot.bp[7] = 6;
        //int[] board_data={2,35,40,39,37,16,29,14,43,4,27,13,38,41,1,26,28,32,17,11,33,51,21,8,6,34,24,42,20,49,45,50,44,0,33,12,19,31,5,3,23,25,22,47,7,36,30,10,18,48,9,15};
        //int[] board_data={14,48,30,29,35,11,3,25,31,28,47,0,9,49,37,39,34,6,23,17,42,1,15,41,33,10,45,51,21,22,46,2,44,36,26,13,32,43,24,7,38,4,20,16,12,40,19,27,5,18,8,50};
        //int[] board_data={13,33,19,4,36,38,25,21,26,22,9,6,12,46,43,44,23,50,2,35,20,31,32,15,34,1,11,40,49,27,39,10,5,16,41,8,45,29,17,18,47,48,51,42,28,24,0,30,3,7,37,14};
        //freecell #278
        //int[] board_data={41,10,17,3,7,15,43,4,16,26,32,29,19,33,49,20,30,11,38,18,40,51,34,22,37,0,28,12,39,42,44,45,27,47,36,1,9,35,50,8,48,25,13,21,2,5,46,23,6,24,14,31};
        //freecell #617
        //int[] board_data={32,35,48,38,3,16,36,26,19,11,43,24,22,25,4,37,41,21,8,40,12,15,0,34,2,47,30,42,17,31,18,20,6,10,7,46,33,45,44,5,27,13,28,29,1,49,39,51,9,23,14,50};
        //freecell #669
        //int[] board_data={22,7,44,18,31,34,50,45,41,39,28,4,25,51,38,0,8,14,40,10,42,11,9,5,24,19,6,30,36,47,33,26,15,16,23,2,1,17,46,29,35,49,43,37,20,48,27,32,21,13,12,3};
        //freecell #1025
        //int[] board_data={27,41,8,21,28,6,35,38,13,34,12,16,20,15,39,37,3,36,51,7,17,18,1,44,24,22,10,30,50,47,11,0,26,2,19,31,32,23,14,46,33,45,49,42,25,5,9,29,40,48,4,43};
        //freecell #1381
        //int[] board_data={6,1,29,31,26,34,17,5,48,35,20,14,33,10,27,30,22,40,25,8,28,4,11,37,43,12,0,24,39,45,7,42,19,15,51,47,9,2,49,41,44,13,36,8,46,23,18,16,50,3,38,32};
        //freecell #3701
        //int[] board_data={2,39,22,28,36,16,15,7,43,27,5,1,51,34,3,41,19,21,24,45,10,17,50,32,49,8,4,46,18,11,0,25,9,42,38,35,30,37,33,14,47,44,48,6,12,13,26,20,31,40,23,29};
        //freecell #1941
        //int[] board_data={34,18,29,39,4,42,51,49,10,23,19,31,0,16,26,33,13,40,12,38,45,25,22,21,46,36,37,41,9,3,14,30,15,44,2,11,17,24,50,32,47,43,6,5,28,35,1,7,20,48,27,8};
        //freecell #7303
        //int[] board_data={17,48,1,35,34,43,3,26,36,7,51,38,42,47,40,12,46,9,25,0,19,6,21,30,8,45,29,28,4,22,32,13,27,41,5,50,18,49,16,24,15,33,31,20,11,39,2,44,14,10,37,23};
        //freecell #9123
        //int[] board_data={47,4,7,8,38,30,20,29,3,31,27,1,42,22,49,50,34,6,23,35,24,2,43,41,37,11,5,0,51,36,25,17,15,28,26,21,19,12,46,48,10,14,39,32,18,33,40,44,16,13,45,9};
        //freecell #10962
        int[] board_data={25,19,33,18,51,7,43,35,28,40,8,12,32,48,30,4,24,9,42,37,36,6,23,26,17,2,50,0,5,41,11,29,34,3,20,49,39,22,31,46,38,47,27,13,21,15,16,10,45,1,44,14};
        //freecell #13304
        //int[] board_data={13,16,28,10,5,4,24,17,51,33,29,2,45,19,31,20,44,7,15,12,21,9,26,50,43,32,35,22,34,0,8,25,40,27,37,47,14,46,11,6,18,39,23,42,48,3,1,36,49,30,41,38};
        //freecell #20003
        //int[] board_data={10,17,29,38,27,0,35,40,51,44,2,22,7,30,5,45,24,23,41,11,1,48,21,16,13,33,4,43,14,26,3,46,36,18,6,50,19,28,15,25,32,9,31,42,49,34,47,20,8,39,12,37};
        //freecell #20095
        //int[] board_data={5,31,24,40,2,39,44,27,10,36,16,1,45,6,18,19,13,21,42,17,43,8,7,48,12,28,3,22,25,26,37,32,0,49,35,29,50,14,51,9,46,33,11,23,41,4,20,15,34,47,38,30};
        //freecell #31945
        //int[] board_data={31,43,20,4,38,39,19,30,41,50,13,8,37,22,14,49,29,35,2,48,21,36,46,42,32,23,9,6,16,10,40,15,28,27,1,18,25,45,7,0,5,47,17,24,11,26,34,33,51,12,3,44};
        //freecell #838856
        //int[] board_data={36,17,4,45,16,8,38,19,41,44,30,9,0,42,37,48,24,23,14,32,25,49,21,18,34,28,47,12,1,33,43,2,7,11,6,26,35,40,15,20,29,39,13,51,46,50,22,3,10,31,27,5};
        //freecell win10 0912
        //int[] board_data={16,51,23,50,36,33,41,49,37,34,32,20,2,11,47,45,8,42,21,12,9,18,10,5,35,4,29,24,27,40,6,31,28,1,13,0,25,46,22,15,3,39,38,14,26,48,43,17,7,30,44,19};
        //freecell win10 1104
        //int[] board_data={4,34,6,20,27,15,42,9,35,24,11,39,40,12,16,46,0,48,51,1,7,29,10,43,36,19,17,8,23,25,33,31,26,22,41,49,47,18,44,13,32,50,37,30,28,21,14,45,3,5,38,2};
        //freecell
        //int[] board_data={10,0,17,44,41,27,14,22,51,46,28,49,35,23,7,19,6,36,21,31,24,18,42,13,38,8,15,47,25,5,43,33,9,3,45,1,39,11,40,16,29,12,48,32,4,34,20,26,50,37,2,30};
        //freecell #
        //int[] board_data={13,17,42,19,4,6,5,18,37,2,15,51,31,20,44,9,8,39,21,32,14,11,46,26,22,12,33,0,24,29,38,27,41,7,1,30,48,36,28,3,34,47,23,40,16,49,10,50,35,45,43,25};
        int cur_col = 0,cur_col_no=0,random_int;
        ArrayList<Integer> random_card=new ArrayList<Integer>();
        /*
        for(int i=0;i<52;i++) random_card.add(i);
        for(int i=0;i<52;i++) {
            random_int= (int) (Math.random() * (52-i));
            curDataRoot.board[cur_col][cur_col_no] = random_card.get(random_int);
            random_card.remove(random_int);
            cur_col_no++;
            if(cur_col_no == curDataRoot.bp[cur_col]) {
                cur_col++;
                cur_col_no = 0;
            }
        }
        //*/
        ///*
        for(int i=0;i<52;i++) {
            curDataRoot.board[cur_col][cur_col_no] = board_data[i];
            cur_col_no++;
            if(cur_col_no == curDataRoot.bp[cur_col]) {
                cur_col++;
                cur_col_no = 0;
            }
        }
        //*/
        
        return curDataRoot;
        
    }
    
    public void freecell(CurData curDataRoot){
        ArrayList<ArrayList<Move3>> srh=new ArrayList<ArrayList<Move3>>();
        ArrayList<Move3> floor;
        ArrayList<Integer> answer=new ArrayList<Integer>();
        HashMap<Long,Integer> srhMap=new HashMap<Long,Integer>();
        CurData curDataRootCopy= new CurData();
        CurData curData0= new CurData();
        CurData curData1= new CurData();
        Move3 root0=new Move3();
        //Significance sign = new Significance();
        
        for(int i=0;i<8;i++) for(int j=0;j<25;j++) curDataRootCopy.board[i][j]=curDataRoot.board[i][j];
        for(int i=0;i<8;i++) curDataRootCopy.bp[i]=curDataRoot.bp[i];
        for(int i=0;i<4;i++) curDataRootCopy.freePos[i]=curDataRoot.freePos[i];
        for(int i=0;i<4;i++) curDataRootCopy.finish[i]=curDataRoot.finish[i];
        
        
        
        root0.curData=curDataRoot;
        
        root0.curData.printCards();
        
        floor = new ArrayList<Move3>();
        floor.add(root0);
        srh.add(floor);
        int xCnt = 0;

        do {
            xCnt++;
            
            if(getNextRoot(xCnt,srhMap,srh,root0,curData0,curData1,answer)==1) break;
            
            srhMap.clear();;
            for(int i=1;i<srh.size();i++) {
                srh.get(i).clear();
            }
            srh.clear();
            floor = new ArrayList<Move3>();
            //floor.add(maxLishun_move);
            floor.add(root0);
            srh.add(floor);    
            //cur_floor = 0;
            //mapHit=0;
            
        }while(true);
        
        System.out.println("################################# ANSWER #################################");
        root0.printAnswer(curDataRootCopy, answer);
        
        //
        srhMap.clear();;
        for(int i=1;i<srh.size();i++) {
            srh.get(i).clear();
        }
        srh.clear();
    }

    /**
     *
     * @param xCnt
     * @param srhMap
     * @param srh
     * @param root0
     * @param curData0
     * @param curData1
     * @param answer
     * @return
     */
    int getNextRoot(int xCnt,HashMap<Long,Integer> srhMap
            ,ArrayList<ArrayList<Move3>> srh
            ,Move3 root0
            ,CurData curData0
            ,CurData curData1
            ,ArrayList<Integer> answer) {
        
        ArrayList<Move3> floor;
        ArrayList<Move3> submoves;
        ArrayList<Move3> floor_current;
        int cur_floor = 0;
        Move3 root = null;
        int returnVal=0;
        
        exitDo:do {
            floor_current = srh.get(cur_floor);
            floor = new ArrayList<Move3>();
            for(int r=0;r<floor_current.size();r++) {
                root = floor_current.get(r);
                //if(count % 10000 ==0 ) {
                //    root.printCards();
                //}
                if(cur_floor>0) root.genData(root0,curData0);
                if(root.curData.finish[0]==13 && root.curData.finish[1]==13 && root.curData.finish[2]==13 && root.curData.finish[3]==13) {
                    returnVal = 1;
                    break exitDo;
                }
                if(root.pressedCards()==0) {
                    root.curData.printCards();
                    returnVal = 1;
                    break exitDo;
                }
                
                //########################### check move, add child
                submoves = this.getAllMoves(srhMap, root, curData1);
                floor.addAll(submoves);
            }
            //########################### child=0
            if(floor.size()>0) {
                cur_floor++;
                srh.add(floor);
                /*
                System.out.println("xCnt="+xCnt + "  floor["+cur_floor+"]="+floor.size());
                if(xCnt==1 && cur_floor<=2) {
                    for(int i=0;i<floor.size();i++)    System.out.println("floor["+ i+ "]=" +floor.get(i).move_from_to_cnt+"    mapstr="+floor.get(i).mapstr);
                }
                */
            }else break;
            
        }while((cur_floor<65-xCnt*15 || xCnt>2 && cur_floor<8)&& srhMap.size()<300000);
        System.out.println("COUNT:"+srhMap.size()+"    CUR_FLOOR:"+cur_floor);
        
        //################################## Select the node with the most child nodes on the fourth floor
        Move3 mp;
        int maxPosterity = 0;
        Move3 maxPosterity_move=null;
        if(returnVal ==0) {
            int loopCnt;
            if(xCnt > 2) loopCnt=8;
            else loopCnt =49-xCnt*19;
            if(loopCnt >= srh.size()) loopCnt= srh.size() -1;
            
            floor = srh.get(loopCnt);
            for(int j=0;j<floor.size();j++) {
                floor.get(j).parent.parent.parent.parent.posteritys++;
            }
            floor= srh.get(loopCnt-4);
            for(int j=0;j<floor.size();j++) {
                if(floor.get(j).posteritys > maxPosterity) {
                    maxPosterity = floor.get(j).posteritys;
                    maxPosterity_move = floor.get(j);
                }
            }
            System.out.println(maxPosterity);
            mp=maxPosterity_move;
        }else {
            mp = root;
            maxPosterity_move = root;
        }
        //############################ Add the solution steps to ArrayList
        int answerStart=answer.size();
        while(mp.parent!=null) {
            answer.add(answerStart,mp.move_from_to_cnt);
            mp=mp.parent;
        }
        
        root0.genRoot(maxPosterity_move);
        root0.curData.printCards();
        
        return returnVal;
    }
    
    ArrayList<Move3> getAllMoves(HashMap<Long,Integer> srhMap,Move3 root,CurData cData) {
        int iTmp,iTmp3,iTmp11,iTmp13;
        ArrayList<Move3> moves= new ArrayList<Move3>();
        ArrayList<Move3> subMoves= new ArrayList<Move3>();
        //=================================check move
        subMoves = check_move_free(srhMap,root,cData);
        moves.addAll(subMoves);

        //=================================check move
        subMoves = check_move_board(srhMap,root,cData);
        moves.addAll(subMoves);
        
        return moves;
    }
    
    ArrayList<Move3> check_move_free(HashMap<Long,Integer> srhMap,Move3 root,CurData cData) {
        int iTmp,iTmp3,iTmp11,iTmp13;
        ArrayList<Move3> moves= new ArrayList<Move3>();
        //free --> board; free-->finish
        for(int i=0;i<4;i++) {
            iTmp = root.curData.freePos[i];
            if(iTmp>-1) {
                for(int j=0;j<8;j++) {
                    if(root.curData.bp[j] == 0) {
                        //search
                            //srhMap.put(mapStr, mx);
                        int cardchk= root.CARD_CHECK(iTmp);
                        if(cardchk == 0) continue;
                        Move3 mx=new Move3(root,cData,8+i,j,cardchk);
                        //mx.COL_MOVE(cardchk);
                        
                        long mapStr=mx.mapStr();
                        if(srhMap.get(mapStr)== null) {
                            srhMap.put(mapStr, 0);
                            mx.curData=null;
                            moves.add(mx);
                        }
                        break;
                    }
                }
                for(int j=0;j<8;j++) {
                    if(root.curData.bp[j] > 0) {
                        iTmp3 = root.curData.board[j][root.curData.bp[j]-1];
                        if(root.curData.bp[j]>0 && (iTmp%13 == iTmp3%13 -1) && (iTmp>25 && iTmp3<=25 ||iTmp<=25 && iTmp3>25)) {
                            //search
                            Move3 mx=new Move3(root,cData,8+i,j);
                                //srhMap.put(mapStr, mx);
                            long mapStr=mx.mapStr();
                            if(srhMap.get(mapStr)== null) {
                                srhMap.put(mapStr, 0);
                                mx.curData=null;
                                moves.add(mx);
                            }
                        }
                    }
                }
                
                if(iTmp%13== root.curData.finish[iTmp/13]) {
                    //search
                    Move3 mx=new Move3(root,cData,8+i,12+iTmp/13);
                    long mapStr=mx.mapStr();
                    if(srhMap.get(mapStr)== null) {
                        srhMap.put(mapStr, 0);
                        mx.curData=null;
                        moves.add(mx);
                    }
                }
            }
        }
        
        return moves;
        
    }

    ArrayList<Move3> check_move_board(HashMap<Long,Integer> srhMap,Move3 root,CurData cData) {
        int iTmp,iTmp3,iTmp11,iTmp13;
        ArrayList<Move3> moves= new ArrayList<Move3>();
        //board --> free; board-->finish; board -->board
        for(int i=0;i<8;i++) {
            if(root.curData.bp[i]==0) {
                int maxcol=root.CARD_CHECK3_FREECOL();
                if(maxcol > -1) {
                    Move3 mx=new Move3(root,cData,i,maxcol,true);
                    long mapStr=mx.mapStr();
                    if(srhMap.get(mapStr)== null) {
                        srhMap.put(mapStr, 0);
                        moves.add(mx);
                    }
                    mx.curData=null;
                }
                break;
                
            }
        }
        
        for(int i=0;i<8;i++) {
            //if(sign.islockcol(i)) continue;
            if(root.curData.bp[i]>0) {
                iTmp=root.curData.board[i][root.curData.bp[i]-1];
                int cardchk= root.CARD_CHECK3(iTmp);
                if(cardchk > 0) {
                    Move3 mx=new Move3(root,cData,i,cardchk,true);
                    long mapStr=mx.mapStr();
                    if(srhMap.get(mapStr)== null) {
                        srhMap.put(mapStr, 0);
                        moves.add(mx);
                    }
                    mx.curData=null;
                }
                

                if(iTmp%13 == root.curData.finish[iTmp/13]) {
                    //search
                    Move3 mx=new Move3(root,cData,i,12+iTmp/13);
                    long mapStr=mx.mapStr();
                    if(srhMap.get(mapStr)== null) {
                        srhMap.put(mapStr, 0);
                        moves.add(mx);
                    }
                    mx.curData=null;
                }
                
            }
        }
        
        for(int i=0;i<8;i++) {
            //if(sign.islockcol(i)) continue;
            if(root.curData.bp[i]>0) {
                iTmp=root.curData.board[i][root.curData.bp[i]-1];
                
                for(int j=0;j<4;j++) {
                    if(root.curData.freePos[j]==-1) {
                        //search
                        Move3 mx=new Move3(root,cData,i,8+j,"");
                        long mapStr=mx.mapStr();
                        if(srhMap.get(mapStr)== null) {
                            if(root.curData.bp[i]>1) {
                                iTmp11 = root.curData.board[i][root.curData.bp[i]-1];
                                iTmp13 = root.curData.board[i][root.curData.bp[i]-2];
                                if(iTmp11 % 13== iTmp13 % 13 -1 && (iTmp11>25 && iTmp13<=25 || iTmp11<25 && iTmp13>=25)) {
                                    //floor_last.add(mx);
                                    if(root.curData.finish[iTmp13/13]== iTmp13%13) {
                                        srhMap.put(mapStr, 0);
                                        moves.add(mx);
                                    }
                                }else {
                                    srhMap.put(mapStr, 0);
                                    moves.add(mx);
                                }
                            }else {
                                srhMap.put(mapStr, 0);
                                moves.add(mx);
                            }
                        }
                        mx.curData=null;
                        break;
                    }
                }
            }
        }
        
        return moves;
        
    }
    
}


class Move3{
    static String[] cellStr= {"1","2","3","4","5","6","7","8","a","b","c","d","h","h","h","h"};
    
    Move3 parent = null;
    int posteritys=0;
    int move_from_to_cnt = -1;
    CurData curData=null;
    

    long mapStr() {
        long l=0;
        
        /*
        for(int i=0;i<8;i++) for(int j=0;j<25;j++) curData.board[i][j]=parent.curData.board[i][j];
        for(int i=0;i<8;i++) this.curData.bp[i]=parent.curData.bp[i];
        for(int i=0;i<4;i++) this.curData.freePos[i]=parent.curData.freePos[i];
        for(int i=0;i<4;i++) this.curData.finish[i]=parent.curData.finish[i];
        recoverOneMove(this.move_from_to_cnt);
        */
        
        for(int i=0;i<4;i++) l+=l*25+curData.finish[i];
        for(int i=0;i<8;i++) l+=l*25+curData.bp[i];
        return l;        
    }
    
    /**
     *
     * @param col
     * @return
     */
    boolean isRegularCol(int col) {
        int iTmp,iTmp3;
        for(int j=curData.bp[col]-1;j>0;j--) {
            iTmp = curData.board[col][j];
            iTmp3 = curData.board[col][j-1];
            if((iTmp%13 == iTmp3%13 -1) && (iTmp>25 && iTmp3<=25 ||iTmp<=25 && iTmp3>25)) {
            }else {
                return false;
            }
        }
        if(curData.bp[col]>1 && curData.board[col][0] % 13 ==12) return true;
        else return false;
    }
    
    int pressedCards() {
        int iTmp,iTmp3,pressed=0;
        for(int i=0;i<8;i++) {
            for(int j=curData.bp[i]-1;j>0;j--) {
                iTmp = curData.board[i][j];
                iTmp3 = curData.board[i][j-1];
                if((iTmp%13 == iTmp3%13 -1) && (iTmp>25 && iTmp3<=25 ||iTmp<=25 && iTmp3>25)) {
                }else {
                    pressed+=j;
                    break;
                }
            }
        }
        return pressed;
        
    }
    
    void recoverOneMove(int moveCode) {
        int mf1,mf2,mt,cards,loop,mf;

        move_from_to_cnt = moveCode;
        mf1=move_from_to_cnt/1000000;
        mf2=(move_from_to_cnt%1000000)/10000;
        mt=(move_from_to_cnt%10000)/100;
        cards=move_from_to_cnt%100;
        if(mf2==0) {
            loop=1;
        }else {
            loop=2;
            mf2--;
        }
        for(int j=0;j<loop;j++) {
            if(j==0) mf=mf1;
            else mf=mf2;
            if(cards==1 || loop==2 && j==0) {
                if(mf>7) {
                    if(mt>11) {
                        //=================== free-->curData.finish
                        this.curData.finish[this.curData.freePos[mf-8]/13]++;
                        this.curData.freePos[mf-8]=-1;
                    }else {
                        //=================== free --> board
                        curData.board[mt][this.curData.bp[mt]]=this.curData.freePos[mf-8];
                        this.curData.bp[mt]++;
                        this.curData.freePos[mf-8]=-1;
                    }
                }else {
                    if(mt>11) {
                        //===================== board-->curData.finish
                        this.curData.finish[curData.board[mf][this.curData.bp[mf]-1]/13]++;
                        curData.board[mf][this.curData.bp[mf]-1]=-1;
                        this.curData.bp[mf]--;
                    }else if(mt>7) {
                        //===================== board-->free
                        this.curData.freePos[mt-8]=curData.board[mf][this.curData.bp[mf]-1];
                        curData.board[mf][this.curData.bp[mf]-1]=-1;
                        this.curData.bp[mf]--;
                    }else {
                        //===================== board-->board
                        curData.board[mt][this.curData.bp[mt]]=curData.board[mf][this.curData.bp[mf]-1];
                        this.curData.bp[mf]--;
                        this.curData.bp[mt]++;
                    }
                }
            }else {
                for(int k=0;k<cards;k++)
                    curData.board[mt][curData.bp[mt]+k] = curData.board[mf][curData.bp[mf]-cards+k];
                curData.bp[mf]-=cards;
                curData.bp[mt]+=cards;
            }
            
        }
        curData.checkFinishCell();
        
    }
    
    void genData(Move3 m0,CurData cData) {
        curData = cData;
        for(int i=0;i<8;i++) for(int j=0;j<25;j++) curData.board[i][j]=m0.curData.board[i][j];
        for(int i=0;i<8;i++) this.curData.bp[i]=m0.curData.bp[i];
        for(int i=0;i<4;i++) this.curData.freePos[i]=m0.curData.freePos[i];
        for(int i=0;i<4;i++) this.curData.finish[i]=m0.curData.finish[i];
        
        
        Move3 mp=this;
        ArrayList<Integer> moves=new ArrayList<Integer>();
        while(mp.parent!=null) {
            moves.add(0,mp.move_from_to_cnt);
            mp=mp.parent;
        }
        
        for(int i=0;i<moves.size();i++) {
            recoverOneMove(moves.get(i));
        }
    }
    
    void genRoot(Move3 m0) {
        
        Move3 mp=m0;
        ArrayList<Integer> moves=new ArrayList<Integer>();
        while(mp.parent!=null) {
            moves.add(0,mp.move_from_to_cnt);
            mp=mp.parent;
        }
        
        for(int i=0;i<moves.size();i++) {
            recoverOneMove(moves.get(i));
        }
    }

    void printAnswer(CurData cData,ArrayList<Integer> answer) {
        curData = cData;
        int move_f2t,mf1,mf2,mt,cards,loop,mf,locksum=0;
        
        for(int i=0;i<answer.size();i++) {
            recoverOneMove(answer.get(i));
            move_f2t=answer.get(i);
            mf1=move_f2t/1000000;
            mf2=(move_f2t%1000000)/10000;
            mt=(move_f2t%10000)/100;
            cards=move_f2t%100;
            if(mf2==0)    System.out.println("step:"+i +"    moving:    "+cellStr[mf1]+cellStr[mt]);
            else System.out.println("step:"+i +"    moving:    "+cellStr[mf1]+cellStr[mt]+"  "+cellStr[mf2-1]+cellStr[mt]);
            this.curData.printCards(move_from_to_cnt);
        }
        

        for(int i=0;i<answer.size();i++) {
            move_f2t=answer.get(i);
            mf1=move_f2t/1000000;
            mf2=(move_f2t%1000000)/10000;
            mt=(move_f2t%10000)/100;
            cards=move_f2t%100;
            if(i%10==0) System.out.println("");
            System.out.print(cellStr[mf1]+cellStr[mt]+"  ");
            if(mf2>0) System.out.print(cellStr[mf2-1]+cellStr[mt]+"  ");
        }
        System.out.println("");
        
        ArrayList<Lock> locks = new ArrayList<Lock>();
        Lock lock;
        int moveFFTC,lockmax=0;
        for(int i=0;i<answer.size();i++) {
            moveFFTC = answer.get(i);
            mf1=moveFFTC/1000000;
            mf2=(moveFFTC%1000000)/10000;
            mt=(moveFFTC%10000)/100;
            cards=moveFFTC%100;
            int j=locks.size()-1;
            while(j>=0) {
                lock=locks.get(j);
                if(lock.fromCol == mt && lock.toCol== mf1 && lock.cardCnt==cards) {
                    System.out.println("lock!!!! AT step:" +i+"   start step:"+lock.step);
                }else {
                    if(lock.toCol == mf1 && lock.cardCnt == cards) {
                        System.out.println("needless move!!!! AT step:" +lock.step +"   cur step:"+i);
                    }else if(lock.fromCol==mf1 || lock.fromCol == mt || lock.toCol == mf1 || lock.toCol ==mt) {
                        locks.remove(j);
                    }
                }
                j--;
            }
            if(mf2==0) {
                lock = new Lock();
                lock.step = i;
                lock.cardCnt = cards;
                lock.fromCol = mf1;
                lock.toCol = mt;
                locks.add(lock);
                if(locks.size()>lockmax) {
                    lockmax=locks.size();
                    System.out.println("lock max="+lockmax);
                }
                locksum += locks.size();
            }
            
        }
        System.out.println("lock average="+locksum*100/answer.size()/100.0);
        
    }
    
    
    public Move3() {
        
    }
    
    public Move3(Move3 m0,CurData cData,int mf,int mt,String str) {
        parent=m0;
        move_from_to_cnt = mf*1000000+mt*100+1;
        curData=cData;
        
        for(int i=0;i<8;i++) for(int j=0;j<25;j++) curData.board[i][j]=m0.curData.board[i][j];
        for(int i=0;i<8;i++) this.curData.bp[i]=m0.curData.bp[i];
        for(int i=0;i<4;i++) this.curData.freePos[i]=m0.curData.freePos[i];
        for(int i=0;i<4;i++) this.curData.finish[i]=m0.curData.finish[i];
        
        //free --> board; free-->curData.finish
        //board --> free; board-->curData.finish; board -->board
        if(mf>7) {
            if(mt>11) {
                //=================== free-->curData.finish
                this.curData.finish[this.curData.freePos[mf-8]/13]++;
                this.curData.freePos[mf-8]=-1;
            }else {
                //=================== free --> board
                curData.board[mt][this.curData.bp[mt]]=this.curData.freePos[mf-8];
                this.curData.bp[mt]++;
                this.curData.freePos[mf-8]=-1;
            }
        }else {
            if(mt>11) {
                //===================== board-->curData.finish
                this.curData.finish[curData.board[mf][this.curData.bp[mf]-1]/13]++;
                curData.board[mf][this.curData.bp[mf]-1]=-1;
                this.curData.bp[mf]--;
            }else if(mt>7) {
                //===================== board-->free
                this.curData.freePos[mt-8]=curData.board[mf][this.curData.bp[mf]-1];
                curData.board[mf][this.curData.bp[mf]-1]=-1;
                this.curData.bp[mf]--;
            }else {
                //===================== board-->board
                curData.board[mt][this.curData.bp[mt]]=curData.board[mf][this.curData.bp[mf]-1];
                this.curData.bp[mf]--;
                this.curData.bp[mt]++;
            }
        }
    }
    
    public Move3(Move3 m0,CurData cData,int mf,int mt) {
        parent=m0;
        move_from_to_cnt = mf*1000000+mt*100+1;
        curData=cData;
        
        //for(int i=0;i<8;i++) for(int j=0;j<25;j++) curData.board[i][j]=m0.curData.board[i][j];
        for(int i=0;i<8;i++) this.curData.bp[i]=m0.curData.bp[i];
        //for(int i=0;i<4;i++) this.curData.freePos[i]=m0.curData.freePos[i];
        for(int i=0;i<4;i++) this.curData.finish[i]=m0.curData.finish[i];
        
        //free --> board; free-->curData.finish
        //board --> free; board-->curData.finish; board -->board
        if(mf>7) {
            if(mt>11) {
                //=================== free-->curData.finish
                this.curData.finish[m0.curData.freePos[mf-8]/13]++;
                //this.curData.freePos[mf-8]=-1;
            }else {
                //=================== free --> board
                //curData.board[mt][this.curData.bp[mt]]=this.curData.freePos[mf-8];
                this.curData.bp[mt]++;
                //this.curData.freePos[mf-8]=-1;
            }
        }else {
            if(mt>11) {
                //===================== board-->curData.finish
                this.curData.finish[m0.curData.board[mf][m0.curData.bp[mf]-1]/13]++;
                //curData.board[mf][this.curData.bp[mf]-1]=-1;
                this.curData.bp[mf]--;
            }else if(mt>7) {
                //===================== board-->free
                //this.curData.freePos[mt-8]=curData.board[mf][this.curData.bp[mf]-1];
                //curData.board[mf][this.curData.bp[mf]-1]=-1;
                this.curData.bp[mf]--;
            }else {
                //===================== board-->board
                //curData.board[mt][this.curData.bp[mt]]=curData.board[mf][this.curData.bp[mf]-1];
                this.curData.bp[mf]--;
                this.curData.bp[mt]++;
            }
        }
    }
    
    /**
     * move one card from free to free col and move cards to this card
     * @param m0
     * @param cData
     * @param mf
     * @param mt
     * @param cardchk
     */
    public Move3(Move3 m0,CurData cData,int mf,int mt,int cardchk) {
        parent=m0;
        int moveFrom = cardchk/100;
        int cards = cardchk % 100;
        move_from_to_cnt = mf*1000000+(moveFrom+1)*10000+mt*100+cards;
        
        curData=cData;
        for(int i=0;i<8;i++) this.curData.bp[i]=m0.curData.bp[i];
        for(int i=0;i<4;i++) this.curData.finish[i]=m0.curData.finish[i];
        curData.bp[mt]++;
        curData.bp[moveFrom]-=cards;
        curData.bp[mt]+=cards;
    }
    

    public Move3(Move3 m0,CurData cData,int mt,int cardchk,boolean bt) {
        parent=m0;
        move_from_to_cnt = cardchk/100*1000000+mt*100+cardchk % 100;
        curData=cData;
        
        //for(int i=0;i<8;i++) for(int j=0;j<25;j++) this.curData.board[i][j]=m0.curData.board[i][j];
        for(int i=0;i<8;i++) this.curData.bp[i]=m0.curData.bp[i];
        //for(int i=0;i<4;i++) this.curData.freePos[i]=m0.curData.freePos[i];
        for(int i=0;i<4;i++) this.curData.finish[i]=m0.curData.finish[i];
        
        int moveFrom = cardchk/100;
        int cards = cardchk % 100;
        ///*
        for(int i=0;i<cards;i++)
            curData.board[mt][curData.bp[mt]+i] = curData.board[moveFrom][curData.bp[moveFrom]-cards+i];
        //*/
        curData.bp[moveFrom]-=cards;
        curData.bp[mt]+=cards;
    }

    int CARD_CHECK(int card) {
        int[] cardcol= {0,0,0,0};
        int cols=0;
        for(int i=0;i<8;i++) {
            if(isRegularCol(i)) continue;
            for(int j=0;j<curData.bp[i];j++) {
                //root.curData.curData.bp[j] == 0 && root.curData.curData.bp[i]>1) || ((iTmp%13 == iTmp3%13 -1) && (iTmp>25 && iTmp3<=25 ||iTmp<=25 && iTmp3>25))) {
                if(curData.board[i][j] % 13== card % 13 -1 && (curData.board[i][j]>25 && card<=25 || curData.board[i][j]<=25 && card>25)) {
                    boolean ck=true;
                    for(int k=j+1;k<curData.bp[i];k++) {
                        if(curData.board[i][k] % 13== curData.board[i][k-1] % 13 -1 && (curData.board[i][k]>25 && curData.board[i][k-1]<=25 || curData.board[i][k]<25 && curData.board[i][k-1]>=25)) {
                        }else {
                            ck = false;
                            break;
                        }
                    }
                    if(ck) {
                        cardcol[cols] = i;
                        cardcol[cols+2] = curData.bp[i] - j; //chang du
                        cols++;
                        break;
                    }
                }
            }
        }
        
        int kongdang=0,konglie=0;
        for(int i=0;i<4;i++) if(curData.freePos[i] == -1) kongdang++;
        for(int i=0;i<8;i++) if(curData.bp[i] == 0) konglie++;
        kongdang = (kongdang+2)*konglie;
        if(cols == 2) {
            if(cardcol[3]>cardcol[2]) {
                if(cardcol[3]<=kongdang) return cardcol[1]*100+cardcol[3];
                else if(cardcol[2]<=kongdang) return cardcol[0]*100+cardcol[2];
                else return 0;
            }else {
                if(cardcol[2]<=kongdang) return cardcol[0]*100+cardcol[2];
                else if(cardcol[2]<=kongdang) return cardcol[1]*100+cardcol[3];
                else return 0;
            }
        }else if(cols == 1) {
            if(cardcol[2]<=kongdang) return cardcol[0]*100+cardcol[2];
            else return 0;
        }else {
            return 0;
        }
    }

    int CARD_CHECK3(int card) {
        int[] cardcol= {0,0,0,0};
        int cols=0;
        for(int i=0;i<8;i++) {
            if(isRegularCol(i)) continue;
            for(int j=0;j<curData.bp[i];j++) {
                //root.curData.curData.bp[j] == 0 && root.curData.curData.bp[i]>1) || ((iTmp%13 == iTmp3%13 -1) && (iTmp>25 && iTmp3<=25 ||iTmp<=25 && iTmp3>25))) {
                if(curData.board[i][j] % 13== card % 13 -1 && (curData.board[i][j]>25 && card<=25 || curData.board[i][j]<=25 && card>25)) {
                    boolean ck=true;
                    for(int k=j+1;k<curData.bp[i];k++) {
                        if(curData.board[i][k] % 13== curData.board[i][k-1] % 13 -1 && (curData.board[i][k]>25 && curData.board[i][k-1]<=25 || curData.board[i][k]<25 && curData.board[i][k-1]>=25)) {
                        }else {
                            ck = false;
                            break;
                        }
                    }
                    if(ck) {
                        cardcol[cols] = i;
                        cardcol[cols+2] = curData.bp[i] - j; //chang du
                        cols++;
                        if(cols>2) {
                            System.out.print("aa");
                        }
                        break;
                    }
                }
            }
        }
        
        int kongdang=0,konglie=0;
        for(int i=0;i<4;i++) if(curData.freePos[i] == -1) kongdang++;
        for(int i=0;i<8;i++) if(curData.bp[i] == 0) konglie++;
        kongdang = (kongdang+1)*(konglie+1);
        if(cols == 2) {
            if(cardcol[3]>cardcol[2]) {
                if(cardcol[3]<=kongdang) return cardcol[1]*100+cardcol[3];
                else if(cardcol[2]<=kongdang) return cardcol[0]*100+cardcol[2];
                else return 0;
            }else {
                if(cardcol[2]<=kongdang) return cardcol[0]*100+cardcol[2];
                else if(cardcol[2]<=kongdang) return cardcol[1]*100+cardcol[3];
                else return 0;
            }
        }else if(cols == 1) {
            if(cardcol[2]<=kongdang) return cardcol[0]*100+cardcol[2];
            else return 0;
        }else {
            return 0;
        }
    }

    int CARD_CHECK3_FREECOL() {
        int[] cardcol= {1,1,1,1,1,1,1,1,0};
        int tmp1,tmp3;
        for(int i=0;i<8;i++) {
            if(curData.bp[i]==0) cardcol[i] = 0;
            else if(curData.bp[i]==1) cardcol[i] = 1;
            else {
                for(int j=curData.bp[i]-1;j>0;j--) {
                    tmp1 = curData.board[i][j];
                    tmp3 = curData.board[i][j-1];
                    if(tmp1 % 13== tmp3 % 13 -1 && (tmp1>25 && tmp3<=25 || tmp1<=25 && tmp3>25)) {
                        cardcol[i]++;
                    }else break;
                }
            }
        }
        
        int kongdang=0,konglie=0;
        for(int i=0;i<4;i++) if(curData.freePos[i] == -1) kongdang++;
        for(int i=0;i<8;i++) if(curData.bp[i] == 0) konglie++;
        kongdang = (kongdang+1)*konglie;
        int max=8;
        for(int i=0;i<8;i++) {
            if(cardcol[i] <= kongdang && cardcol[i] < curData.bp[i] && cardcol[i]>cardcol[max]) max=i;
        }
        if(max == 8) return -1;
        return max*100+cardcol[max];
        
    }
    
    /*
    void COL_MOVE(int cardchk) {
        int moveto=(move_from_to_cnt%10000)/100;
        int moveFrom = cardchk/100;
        int cards = cardchk % 100;
        move_from_to_cnt = move_from_to_cnt + (cardchk/100+1)*10000;
        move_from_to_cnt = move_from_to_cnt/100*100+cards;
        for(int i=0;i<cards;i++) curData.board[moveto][1+i] = curData.board[moveFrom][curData.bp[moveFrom]-cards+i];
        curData.bp[moveFrom]-=cards;
        curData.bp[moveto]+=cards;
    }
    */

}

class CurData{
    static String[] huase= {"♣","♠","◆","♥"};
    static String[] paidian= {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
    
    public int[][] board = new int[8][25];
    public int[] bp = new int[8];
    public int[] freePos = {-1,-1,-1,-1};
    public int[] finish = new int[4];

    String cardStr(int c) {
        if(c<0) return "-";
        return huase[c/13]+paidian[c%13];
    }
    String cardStr(int col,int val) {
        if(val==0) return "-";
        return huase[col]+paidian[val-1];
    }
    void printCards() {
        System.out.println("|===============================================================|");
        System.out.println("|        FREE:        |        REC:        |");
        System.out.println("|"+cardStr(freePos[0]) + "    "+ cardStr(freePos[1]) + "    "+cardStr(freePos[2]) + "    "+cardStr(freePos[3])+ "    |"+ cardStr(0,finish[0]) + "    "+ cardStr(1,finish[1]) + "    "+cardStr(2,finish[2]) + "    "+cardStr(3,finish[3])+"    |");
        System.out.println("|===============================================================|");
        int max=0;
        String str;
        for(int i=0;i<8;i++) if(max<bp[i]) max= bp[i];
        for(int i=0;i<max;i++) {
            str = "";
            for(int j=0;j<8;j++) {
                if(i<bp[j]) str+=cardStr(board[j][i]);
                str+="    ";
            }
            System.out.println(str);
        }
        
    }
    
    String repeatChar(String s,int repeat) {
        String str="";
        for(int i=0;i<repeat;i++) str+=s;
        return str;
    }

    void printCards(int movefromto) {
        System.out.println("|===============================================================|");
        System.out.println("|        FREE:        |        REC:        |");
        System.out.println("|"+cardStr(freePos[0]) + "    "+ cardStr(freePos[1]) + "    "+cardStr(freePos[2]) + "    "+cardStr(freePos[3])+ "    |"+ cardStr(0,finish[0]) + "    "+ cardStr(1,finish[1]) + "    "+cardStr(2,finish[2]) + "    "+cardStr(3,finish[3])+"    |");
        System.out.println("|===============================================================|");
        
        int mf=movefromto/1000000;
        int mt=(movefromto%10000)/100;
        String moveSign="";
        if(mf<8 && mf<mt && mt<8) moveSign = repeatChar("    ",mf)+"┌"+repeatChar("─",(mt-mf)*8)+"↓";
        else if(mf<8 && mt>8 && mt>mf+8) moveSign = repeatChar("    ",mf)+"┌"+repeatChar("─",(mt-mf-8)*8)+"↑";
        else if(mf>=8 && mt<8 && mt+8>mf) moveSign = repeatChar("    ",mf-8)+"└"+repeatChar("─",(mt+8-mf)*8)+"↓";
        else if(mf>=8 && mt>mf) moveSign = repeatChar("    ",mf-8)+"└"+repeatChar("─",(mt-mf)*8)+"↑";
        else if(mf<8 && mt<mf) moveSign = repeatChar("    ",mt)+"↓"+repeatChar("─",(mf-mt)*8)+"┐";
        else if(mf<8 && mt>=8 && mt<mf+8) moveSign = repeatChar("    ",mt-8)+"↑"+repeatChar("─",(mf+8-mt)*8)+"┐";
        else if(mf>=8 && mt<8 && mt<mf-8) moveSign = repeatChar("    ",mt)+"↓"+repeatChar("─",(mf-8-mt)*8)+"┘";
        else if(mf>=8 && mt>mf) {}
        else if(mt == mf+8)    moveSign = repeatChar("    ",mf)+"↑";
        else if(mt == mf-8)    moveSign = repeatChar("    ",mt)+"↓";
        System.out.println(moveSign);
        
        int max=0;
        String str;
        for(int i=0;i<8;i++) if(max<bp[i]) max= bp[i];
        for(int i=0;i<max;i++) {
            str = "";
            for(int j=0;j<8;j++) {
                if(i<bp[j]) str+=cardStr(board[j][i]);
                str+="    ";
            }
            System.out.println(str);
        }
        
    }
    
    void checkFinishCell() {
        int upCards=1;
        int card,cardPoint,corresponding1,corresponding2;
        while(upCards>0) {
            upCards=0;
            for(int i=0;i<8;i++) {
                if(bp[i]>0) {
                    card=board[i][bp[i]-1];
                    cardPoint = card%13;
                    if(card<26) {
                        corresponding1=2;
                        corresponding2=3;
                    }else {
                        corresponding1=0;
                        corresponding2=1;
                    }
                    if(cardPoint == finish[card/13] && (cardPoint <2 || (finish[corresponding1]>=cardPoint && finish[corresponding2]>=cardPoint))) {
                        bp[i]--;
                        finish[card/13]++;
                        upCards++;
                    }
                }
            }
            for(int i=0;i<4;i++) {
                if(freePos[i]>=0) {
                    card=freePos[i];
                    cardPoint = card%13;
                    if(card<26) {
                        corresponding1=2;
                        corresponding2=3;
                    }else {
                        corresponding1=0;
                        corresponding2=1;
                    }
                    if(cardPoint == finish[card/13] && (cardPoint <2 || (finish[corresponding1]>=cardPoint && finish[corresponding2]>=cardPoint))) {
                        freePos[i]=-1;
                        finish[card/13]++;
                        upCards++;
                    }
                }
            }
        }
    }
    
}

class Lock{
    int step;
    int type;
    int fromCol;
    int toCol;
    int card;
    int cardCnt;
}


原文地址:https://www.cnblogs.com/nocomment/p/8282507.html