1. 程式人生 > >空當接龍求解:java版廣度優先

空當接龍求解:java版廣度優先

nta rep sig solution respond || child 重新 util

說是廣度優先,其實一搜到底還是不可能的,通過多少步(比如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;
}


空當接龍求解:java版廣度優先