重构华容道自动求解

xiaoxiao2021-02-28  14

之前的关于华容道自动求解的代码,变量名的命名很不规范,结构也不太容易理解,过一段时间后,重新来看,又会不知道以前的代码的意思了,明明之前已经看懂,结果现在又不懂了,很浪费时间。所以,应该自己再来针对代码的可读写进行重构。

package game.hrd.game.hrd.refactor; import java.util.ArrayList; /** * Created by huangcongjie on 2017/12/20. */ public class Solver { HrdNode[] queue; int searchAmount = 0; int processingIndex = 0; int maxAmount = Integer.MAX_VALUE; private void addToQueue(HrdNode node) { if (searchAmount >= maxAmount) { System.out.println("对溢出"); return; } queue[searchAmount] = node; searchAmount++; } //--广度优先-- public int bfs(int[] layout, boolean useHash) { // System.out.println("use hash checker: " + useHash); long t1 = System.currentTimeMillis(); long cost = 0; IAnalyzer analyzer = useHash ? new HashLayoutAnalyzer() : new LayoutAnalyzer(); HrdNode root = new HrdNode(layout, analyzer, useHash); IChecker checker = useHash ? new LayoutToHash() : new LayoutToCode(root.layout); if (useHash) { maxAmount = 40 * 1024; } else { maxAmount = ((LayoutToCode) checker).codeTotalNum / 10; } queue = new HrdNode[maxAmount]; HrdNode curNode = root; addToQueue(root); while (processingIndex < searchAmount) { // System.out.println("searchAmount: " + searchAmount); HrdNode answer = curNode.giveBirth(checker, new IListener() { @Override public void validNodeCreated(HrdNode child) { addToQueue(child); } }); if (answer != null) { cost = System.currentTimeMillis() - t1; System.out.println("found answer! total steps: " + answer.level + " cost: " + cost + "ms"); if (checker instanceof LayoutToHash) { System.out.println("hash conflicts: " + ((LayoutToHash) checker).cht ); } displaySolution(answer); return 1; } processingIndex++; curNode = queue[processingIndex]; } cost = System.currentTimeMillis() - t1; System.out.println("already searched all nodes, cannot found answer! cost: " + cost + "ms"); return 0; } public interface IListener { void validNodeCreated(HrdNode child); } private void displaySolution(HrdNode hrdObj) { ArrayList<HrdNode> list = new ArrayList<>(); list.add(hrdObj); HrdNode node = hrdObj; while (node.parent != null) { list.add(node.parent); node = node.parent; } for (int i = list.size() - 1; i >= 0; i--) { displayStep(list.get(i)); } } private void displayStep(HrdNode hrdObj) { System.out.println("第" + hrdObj.level + "步"); int[] layout = hrdObj.isHashLayout() ? HrdUtil.convertToScreen(hrdObj.layout) : hrdObj.layout; for (int i = 0; i < layout.length; i += 4) { System.out.println(String.format("%d\t%d\t%d\t%d", layout[i], layout[i+1], layout[i+2], layout[i+3])); } System.out.println(); } } package game.hrd.game.hrd.refactor; /** * Created by huangcongjie on 2017/12/20. */ public interface IAnalyzer { void analyze(HrdNode hrdLayout); void step(int[] layout, int src, int dst); } package game.hrd.game.hrd.refactor; /** * Created by huangcongjie on 2017/12/20. */ public interface IChecker { //return true if layout is unique, first appear boolean checkAndModify(int[] layout); } package game.hrd.game.hrd.refactor; import game.hrd.ZBD; /** * Created by huangcongjie on 2017/12/20. */ public class LayoutToHash implements IChecker { private long[] hsb; private long[] hsb2; public int cht; //哈希冲突次数 //使用128k(17位)哈希表,如果改用更大的表,相应的哈希计算位数也要改 static private final int hSize = 128 * 1024; public int count = 0; public LayoutToHash() { hsb = new long[hSize + hSize/4 + 64]; hsb2 = new long[hsb.length / 4]; cht = 0; } @Override public boolean checkAndModify(int[] layout) { if (check(layout) == 1) { symmetricCheck(layout); return true; } return false; } public int check(int[] layout) { // count++; //生成散列参数n1,n2,m0 //以下参数生成算法不保证参数与棋盘的唯一对应关系,因此理论上存在哈希表冲突判断错误的可能 //只不过产生错误的可能性几乎可能完全忽略 int[] p = ZBD.layoutCompress(layout); long n1 = ( ( p[1] << 3 )+ (p[2] << 5) + p[0]); //每次折叠时都应充分发挥各子作用,增强散列 long n2 = ( ( p[3] << 1) + (p[4] << 4) ); long m0 = (n2 << 6) ^ (n1 << 3); //增强散列参数 //第一哈希处理 long h1 = ( n1 + n2 + m0 ) & 0x0000ffffffffL; long h = (( h1 & 0x0001FFFF ) ^ ( h1 >> 17 )) & 0x0000ffffffffL; int h0 = (int) h; // if (count < 1000) // System.out.println("PmHx check count: " + count + ", h: " + h0); for (int i = 0; i < 2; i++) { if (hsb[h0] == 0) { //从未出现过的布局 hsb[h0] = h1; return 1; } if (hsb[h0] == h1) { //已经出现过的布局 return 0; } //有哈希冲突 h0++; } //多次查表,最多32次 //第二哈希处理 h1 = (n1 - n2 + m0) & 0x0000ffffffffL; h = (( h1 & 0x00007FFF ) ^ ( h1 >> 19 )) & 0x0000ffffffffL; h0 = (int) h; for(int i = 0; i < 10; i++) { if (hsb2[h0] == 0) { hsb2[h0] = h1; return 1; } if (hsb2[h0] == h1) { return 0; } h0++; } //首次查表 cht++; //哈希冲突计数(通过5次哈希,一般情况下冲突次数为0) return 1; } //按左右对称规则考查棋盘,并记录到哈希表 public void symmetricCheck(int[] q20) { int[] p20 = new int[20]; for (int i = 0; i < 20; i+= 4) { p20[i] = q20[i+3]; p20[i+1] = q20[i+2]; p20[i+2] = q20[i+1]; p20[i+3] = q20[i]; } check(p20); } } package game.hrd.game.hrd.refactor; import game.hrd.LocalConst; /** * Created by huangcongjie on 2017/12/20. */ //盘面编码类 public class LayoutToCode implements IChecker { //组合序号表 short[] Hz; //横将 short[] Sz; //竖将 short[] Bz; //小兵 //权值表 int[] Hw; int[] Sw; int[] Mw; public int codeTotalNum; int[] JD; //节点字典 public LayoutToCode(int[] layout) { Hz = new short[4096 * 3]; Sz = new short[4096]; Bz = new short[128]; //C12取5=792 Hw = new int[792*2]; Sw = new int[792]; int i,j,k; int Hn=0, Bn=0, Sn=0; //各类子数目,大王默认为1不用计数 for(i=0;i<20;i++){ //计算各种棋子的个数 if(LocalConst.U[layout[i]]=='B') Bn++; if(LocalConst.U[layout[i]]=='H') Hn++; if(LocalConst.U[layout[i]]=='C') Sn++; } Hn /= 2; Sn /= 2; int[] WQ2 = LocalConst.WQ2; int Hmax=WQ2[11],Smax=WQ2[12-Hn*2],Bmax=WQ2[16-(Hn+Sn)*2]; //各种子的最大二进位数 short Hx=0,Sx=0,Bx=0; //各种棋子组合的最大序号 //初始化组合序号表 for(i=0; i<4096; i++){ for(j=0,k=0;j<12;j++) { if((i & WQ2[j]) > 0) { k++; //计算1的个数 } } if(k==Hn && i<Hmax) { Hz[i] = Hx++; } if(k==Sn && i<Smax) { Sz[i]=Sx++; } if(k==Bn && i<Bmax) { Bz[i]=Bx++; } } int Sq=Bx,Hq=Bx*Sx,Mq=Bx*Sx*Hx; //竖将位权,横将位权,王位权 Mw = new int[12]; Hw = new int[Hx]; Sw = new int[Sx]; for(i=0;i<12;i++) Mw[i]=i*Mq; //初始化大王权值表 for(i=0;i<Hx;i++) Hw[i]=i*Hq; //初始化横将权值表 for(i=0;i<Sx;i++) Sw[i]=i*Sq; //初始化竖将权值表 codeTotalNum = Mq*12; JD = new int[codeTotalNum]; } @Override public boolean checkAndModify(int[] layout) { int code = encode(layout); if (JD[code] == 0) { // js2++; //js搜索总次数计数和js2遍历的实结点个数 JD[code] = 1; int symmetricCode = symmetricEncode(layout); JD[symmetricCode] = 1; return true; } return false; } //盘面编码 private int encode(int[] layout) { int Bb=0,Bd=-1; //小兵序号记录器 int Sb=0,Sd=-1; //竖条序号记录器 int Hb=0,Hd=-1; //横条序号记录器 int Mb = 0; //大王序号记录器 int c,lx; int[] f = new int[16]; for(int i = 0; i < 20; i++){ c=layout[i]; lx = LocalConst.U[c]; //当前的值 if(lx=='M') { //大王定序 if(f[c] == 0) { Mb = i - LocalConst.ROW[i]; f[c] = 1; } continue; } if (LocalConst.COL[i]<3 && LocalConst.U[layout[i+1]] <= 'H') { Hd++; //横条位置序号(编号) } if (lx == 'H') {//横将定序,转为二进制进行询址得Hb if(f[c] == 0) { Hb += LocalConst.WQ2[Hd]; f[c]=1; } continue; } if (LocalConst.ROW[i]<4 && LocalConst.U[layout[i+4]]<='C') { Sd++; //竖将位置序号(编号) } if (lx=='C') { //竖条定序,转为二进制进行询址得Sb if(f[c] == 0) { Sb += LocalConst.WQ2[Sd]; f[c]=1; } continue; } if(lx<='B') Bd++; //小兵位置序号(编号) if(lx=='B') Bb += LocalConst.WQ2[Bd]; //小兵定序,转为二进制进行询址得Bb } //Hb,Sb,Bb为组合序号,"横刀立马"最大值为小兵C(6,4)-1=15-1,竖条C(10,4)-1=210-1 Bb=Bz[Bb]; Sb=Sz[Sb]; Hb=Hz[Hb];//询址后得得Bb,Sb,Hb组合序号 return Bb+Sw[Sb]+Hw[Hb]+Mw[Mb]; //用位权编码,其中Bb的位权为1 } //按左右对称规则考查棋盘,对其编码 private int symmetricEncode(int[] q){ char i; int[] q2 = new int[20]; for(i=0; i<20; i+=4) { q2[i]=q[i+3]; q2[i+1]=q[i+2]; q2[i+2]=q[i+1]; q2[i+3]=q[i]; } return encode(q2); } } package game.hrd.game.hrd.refactor; import game.hrd.LocalConst; /** * Created by huangcongjie on 2017/12/20. */ public class LayoutAnalyzer implements IAnalyzer { @Override public void analyze(HrdNode hrdLayout) { int i,col,k1=0,k2=0,h=0; //i,列,空格1位置,空格2位置,h为两空格的联合类型 int c,lx; //f[]记录已判断过的棋字 int[] f = new int[16]; hrdLayout.totalChoices=0; //计步复位 int[] layout = hrdLayout.layout; for(i=0; i<20; i++){ if(layout[i] == 0) { k1=k2; k2=i; //查空格的位置 } } if (k1 + 4 == k2) { h = 1; //空格竖联合 } if (k1 + 1 == k2 && LocalConst.COL[k1] < 3) { h = 2; //空格横联合 } for (i = 0; i < 20; i++) { c = layout[i]; lx = LocalConst.U[c]; col = LocalConst.COL[i]; if (f[c] == 1) { continue; } switch (lx) { case 'M'://曹操可能的走步 if (i + 8 == k1 && h == 2) { //向下 hrdLayout.addChoice(i, i + 4); } if (i - 4 == k1 && h == 2) { //向上 hrdLayout.addChoice(i, i - 4); } if (col < 2 && i + 2 == k1 && h == 1) { //向右 hrdLayout.addChoice(i, i + 1); } if (col > 0 && i - 1 == k1 && h == 1) { //向左 hrdLayout.addChoice(i, i - 1); } f[c] = 1; break; case 'H': //关羽可能的走步 if (i + 4 == k1 && h == 2) { hrdLayout.addChoice(i, i + 4); } if (i - 4 == k1 && h == 2) { hrdLayout.addChoice(i, i - 4); } if (col < 2 && (i + 2 == k1 || i + 2 == k2)) { hrdLayout.addChoice(i, i + 1); if (h == 2) { hrdLayout.addChoice(i, k1); } } if (col > 0 && (i - 1 == k1 || i - 1 == k2)) { hrdLayout.addChoice(i, i - 1); if (h == 2) { hrdLayout.addChoice(i, k1); } } f[c] = 1; break; case 'C': //张飞,马超,赵云,黄忠可能的走步 if (i + 8 == k1 || i + 8 == k2) { hrdLayout.addChoice(i, i + 4); if (h == 1) { hrdLayout.addChoice(i, k1); } } if (i - 4 == k1 || i - 4 == k2) { hrdLayout.addChoice(i, i - 4); if (h == 1) { hrdLayout.addChoice(i, k1); } } if (col < 3 && i + 1 == k1 && h == 1) { hrdLayout.addChoice(i, i + 1); } if (col > 0 && i - 1 == k1 && h == 1) { hrdLayout.addChoice(i, i - 1); } f[c] = 1; break; case 'B': if (i + 4 == k1 || i + 4 == k2) { if (h > 0) { hrdLayout.addChoice(i, k1); hrdLayout.addChoice(i, k2); } else { hrdLayout.addChoice(i, i + 4); } } if (i - 4 == k1 || i - 4 == k2) { if (h > 0) { hrdLayout.addChoice(i, k1); hrdLayout.addChoice(i, k2); } else { hrdLayout.addChoice(i, i - 4); } } if (col < 3 && (i + 1 == k1 || i + 1 == k2)) { if (h > 0) { hrdLayout.addChoice(i, k1); hrdLayout.addChoice(i, k2); } else { hrdLayout.addChoice(i, i + 1); } } if (col > 0 && (i - 1 == k1 || i - 1 == k2)) { if (h > 0) { hrdLayout.addChoice(i, k1); hrdLayout.addChoice(i, k2); } else { hrdLayout.addChoice(i, i - 1); } } break; } } } //走一步函数 @Override public void step(int[] layout, int src, int dst) { int c = layout[src]; int lx = LocalConst.U[c]; switch(lx) { case 'B': layout[src] = 0; layout[dst] = c; break; case 'C': layout[src] = layout[src+4] = 0; layout[dst] = layout[dst+4] = c; break; case 'H': layout[src] = layout[src+1]=0; layout[dst] = layout[dst+1]=c; break; case 'M': layout[src] = layout[src+1]= layout[src+4]=layout[src+5]=0; layout[dst] = layout[dst+1]= layout[dst+4]=layout[dst+5]=c; break; } } } package game.hrd.game.hrd.refactor; import game.hrd.LocalConst; /** * Created by huangcongjie on 2017/12/20. */ public class HashLayoutAnalyzer implements IAnalyzer { private int k1 = -1; //空格1位置 private int k2 = -1; //空格2位置 private int h; //两空格的联合类型, {0:不联合,1:竖联合,2:横联合} @Override public void analyze(HrdNode hrdLayout) { int i=0; //i,列 k1 = k2 = -1; h = 0; int[] layout = hrdLayout.layout; for(i=0; i<20; i++){ if(layout[i] == 0) { if (k1 == -1) { k1 = i; } else { k2 = i; break; } } } if (k1 + 4 == k2) { h = 1; //空格竖联合 } if (k1 + 1 == k2 && LocalConst.COL[k1] < 3) { h = 2; //空格横联合 } int col1 = LocalConst.COL[k1]; int col2 = LocalConst.COL[k2]; if (col1 > 0) { i = k1 - 1; zinb(hrdLayout, i, k1); if (layout[i] == 3) { if (h == 1) hrdLayout.addChoice(i, k1); } if (layout[i] == 5) { if (h == 1) hrdLayout.addChoice(i - 1, k1 - 1); } if (layout[i] == 4) { if (h == 2) { hrdLayout.addChoice(i - 1, k2 - 1); } hrdLayout.addChoice(i - 1, k1 - 1); } } if (col1 < 3) { i = k1 + 1; zinb(hrdLayout, i, k1); if (layout[i] == 3) { if (h == 1) hrdLayout.addChoice(i, k1); } if (layout[i] == 5) { if (h == 1) hrdLayout.addChoice(i, k1); } if (layout[i] == 4) { hrdLayout.addChoice(i, k1); //如果横联合,k1不是第一空,所以不用判断h } } if (k1 > 3) { i = k1 - 4; zinb(hrdLayout, i, k1); if (layout[i] == 4 && layout[i+1] == 4 && (col1 != 1 || layout[i-1] != 4) ) { if (h == 2) hrdLayout.addChoice(i, k1); } if (layout[i] == 1) { if (layout[i-4] == 3) { if (h == 1) { hrdLayout.addChoice(i - 4, k2 - 4); } hrdLayout.addChoice(i - 4, k1 - 4); } if (layout[i-4] == 5 && layout[i-3] == 5) { if (h == 2) hrdLayout.addChoice(i - 4, k1 - 4); } } } if (k1 < 16) { i = k1 + 4; zinb(hrdLayout, i, k1); if (layout[i] == 3) hrdLayout.addChoice(i, k1); if (layout[i] == 4 && i < 19 && layout[i+1] == 4 && (col1 != 1 || layout[i-1] != 4) ) { if (h == 2) { hrdLayout.addChoice(i, k1); } } if (layout[i] == 5 && layout[i+1] == 5) { if (h == 2) hrdLayout.addChoice(i, k1); } } if (col2 > 0) { i = k2 - 1; zinb(hrdLayout, i, k2); if (layout[i] == 4) { hrdLayout.addChoice(i - 1, k2 - 1); } } if(k2>3) { i = k2 - 4; zinb(hrdLayout, i, k2); if(layout[i]==1 && layout[i-4] == 3) { hrdLayout.addChoice(i - 4, k2 - 4); } } if(col2<3) { i = k2 + 1; zinb(hrdLayout, i, k2); if(layout[i]==4) { if(h==2) { hrdLayout.addChoice(i, k1); } hrdLayout.addChoice(i, k2); } } if(k2<16) { i = k2 + 4; zinb(hrdLayout, i, k2); if(layout[i]==3) { if(h==1) { hrdLayout.addChoice(i, k1); } hrdLayout.addChoice(i, k2); } } } private void zinb(HrdNode hrdLayout, int src, int dst) { if (hrdLayout.layout[src] == 2) { //小兵 if (h > 0) { hrdLayout.addChoice(src, k1); hrdLayout.addChoice(src, k2); } else { hrdLayout.addChoice(src, dst); } } } //走一步函数 @Override public void step(int[] layout, int src, int dst) { int c = layout[src]; int lx = c; if (c == 1) { lx = layout[src-4]; } switch(lx) { case 2: //兵 layout[src] = 0; layout[dst] = c; break; case 3: //竖 layout[src] = layout[src+4] = 0; layout[dst] = c; layout[dst+4] = 1; break; case 4: //横 layout[src] = layout[src+1]=0; layout[dst] = layout[dst+1]=c; break; case 5: //王 layout[src] = layout[src+1]= layout[src+4]=layout[src+5]=0; layout[dst] = layout[dst+1]= c; layout[dst+4]=layout[dst+5]= 1; break; } } } package game.hrd.game.hrd.refactor; /** * Created by huangcongjie on 2017/12/20. */ public class HrdNode { public int[] layout; public int level = 0; public HrdNode parent = null; //记录上次移动的索引 private int preMovedIndex = -1; //原位置,目标位置,最多只会有10步 public int[] srcArr = new int[10]; public int[] dstArr = new int[10]; public int totalChoices = 0; private IAnalyzer analyzer; private boolean isHashLayout; public HrdNode(int[] layout, IAnalyzer analyzer, boolean useHash) { this.layout = layout; this.analyzer = analyzer; isHashLayout = useHash; analyzer.analyze(this); } public void addChoice(int src, int dst) { srcArr[totalChoices] = src; dstArr[totalChoices] = dst; totalChoices++; } public boolean isGoal() { if (isHashLayout) { return layout[13] == 5 && layout[14] == 5; } return layout[17] == 15 && layout[18] == 15; } public HrdNode giveBirth(IChecker encoder, Solver.IListener listener) { HrdNode answer = null; for (int i = 0; i < totalChoices; i++) { if (srcArr[i] == preMovedIndex) { //和上次移动同一个棋子时不搜索,可提速20%左右 continue; } int[] childLayout = HrdUtil.copy(layout); analyzer.step(childLayout, srcArr[i], dstArr[i]); if (encoder.checkAndModify(childLayout)) { //get permission to giveBirth HrdNode child = new HrdNode(childLayout, analyzer, isHashLayout); child.parent = this; child.level = this.level + 1; child.setPreMovedIndex(dstArr[i]); if (listener != null) { listener.validNodeCreated(child); if (child.isGoal()) { return child; } } } } return answer; } // public int getValidChildrenNum() { // return validChildrenNum; // } public boolean isHashLayout() { return isHashLayout; } public void setPreMovedIndex(int preMovedIndex) { this.preMovedIndex = preMovedIndex; } } package game.hrd.game.hrd.refactor; /** * Created by huangcongjie on 2017/12/20. */ public class HrdUtil { /** * * @param layout int array which contains 20 integers * @return an array only contains 5 integers */ static public int[] layoutCompress5(int[] layout) { int[] ret = new int[5]; for (int i = 0; i < 5; i++) { int a = i * 4; ret[i] = layout[a] | (layout[a+1] << 8) | (layout[a+2] << 16) | (layout[a+3] << 24); } return ret; } // int[] layout = { // 6, 15, 15, 7, // 6, 15, 15, 7, // 8, 11, 11, 5, // 8, 3, 4, 5, // 2, 0, 0, 1 // }; // int[] ret = { // 3, 5, 5, 3, // 1, 1, 1, 1, // 3, 4, 4, 3, // 1, 2, 2, 1, // 2, 0, 0, 2 // }; //layout 用1-15表示各棋子,空位用0表示,兵1-4,竖将5-9,横将10-14,大王15 static public int[] convertToHashLayout(int[] layout) { int[] ret = new int[20]; //用1-15表示各棋子,空位用0表示,兵1-4,竖将5-9,横将10-14,大王15 for (int i = 0; i < layout.length; i++) { int cur = layout[i]; if (cur == 15) { if (i-4 >= 0 && ret[i-4] == 5) { ret[i] = 1; } else { ret[i] = 5; } } else if (cur >= 10 && cur <= 14) { ret[i] = 4; } else if (cur >= 5 && cur <= 9) { if (i-4 >= 0 && ret[i-4] == 3) { ret[i] = 1; } else { ret[i] = 3; } } else if (cur >= 1 && cur <= 4) { ret[i] = 2; } else { ret[i] = cur; //空格 } } return ret; } static public int[] convertToScreen(int[] hashLayout) { int[] ret = new int[20]; for (int i = 0; i < hashLayout.length; i++) { int cur = hashLayout[i]; if (cur == 1) { ret[i] = hashLayout[i-4]; } else { ret[i] = hashLayout[i]; } } return ret; } static public int[] copy(int[] layout) { int[] ret = new int[layout.length]; for (int i = 0; i < layout.length; i++) { ret[i] = layout[i]; } return ret; } } package game.hrd; public class LocalConst { //用1-15表示各棋子,空位用0表示,兵1-4,竖将5-9,横将10-14,大王15 //大王只能1个,将必须5个(横竖合计),兵必须为4个 // static final public String U = "ABBBBCCCCCHHHHHM"; static final public int[] U = {'A','B','B','B','B','C','C','C','C','C','H','H','H','H','H','M'}; static final public int[] COL = {0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3}; //列号表 static final public int[] ROW = {0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4}; //行号表 static final public int[] WQ2 = {1,2,4,8,16, 32,64,128,256,512, 1024,2048,4096}; //二进制位权表(12个) //使用128k(17位)哈希表,如果改用更大的表,相应的哈希计算位数也要改 static final public int hsize = 128 * 1024; static final public String[] layoutNames = {"横刀立马", "指挥若定", "将拥曹营", "齐头并进", "兵分三路", "雨声淅沥", "左右布兵", "桃花园中", "一路进军", "一路顺风", "围而不歼", "捷足先登", "插翅难飞", "殊途同归", "守口如瓶1", "守口如瓶2", "双将挡路", "横马当关", "层层布防", "兵将联防", "兵挡将阻", "堵塞要道", "瓮中之鳖", "层峦叠嶂", "水泄不通", "四路进兵", "入地无门", "勇闯五关", "四面楚歌", "前呼后拥", "兵临曹营", "五将逼宫", "前挡后阻", "近在咫尺", "走投无路", "比翼横空", "夹道藏兵", "屯兵东路", "四将连关", "峰回路转"}; static final public int[][] allLayouts = {{ //横刀立马, 1横4竖,难度81 6, 15, 15, 7, 6, 15, 15, 7, 8, 10, 10, 5, 8, 3, 4, 5, 2, 0, 0, 1 }, { //指挥若定,1横4竖,70 6, 15, 15, 7, 6, 15, 15, 7, 2, 10, 10, 1, 8, 3, 4, 5, 8, 0, 0, 5 }, { //将拥曹营,1横4竖 72 0, 15, 15, 0, 6, 15, 15, 7, 6, 8, 5, 7, 1, 8, 5, 2, 10, 10, 3, 4 }, { //齐头并进,1横4竖 60 6, 15, 15, 7, 6, 15, 15, 7, 4, 3, 2, 1, 8, 10, 10, 5, 8, 0, 0, 5 }, { //兵分三路,1横4竖 72 1, 15, 15, 2, 6, 15, 15, 7, 6, 10, 10, 7, 8, 3, 4, 5, 8, 0, 0, 5 }, { //雨声淅沥,1横4竖 47 6, 15, 15, 4, 6, 15, 15, 3, 8, 10, 10, 5, 8, 7, 0, 5, 2, 7, 0, 1 }, { //左右布兵,1横4竖 54 1, 15, 15, 3, 2, 15, 15, 4, 8, 6, 7, 5, 8, 6, 7, 5, 0, 10, 10, 0 }, { //桃花园中,1横4竖 70 1, 15, 15, 3, 8, 15, 15, 5, 8, 6, 7, 5, 2, 6, 7, 4, 0, 10, 10, 0 }, { //一路进军,1横4竖 58 6, 15, 15, 1, 6, 15, 15, 2, 8, 7, 5, 3, 8, 7, 5, 4, 0, 10, 10, 0 }, { //一路顺风,1横4竖 39 6, 15, 15, 1, 6, 15, 15, 2, 8, 10, 10, 5, 8, 3, 7, 5, 0, 4, 7, 0 }, { //围而不歼,1横4竖 62 6, 15, 15, 1, 6, 15, 15, 2, 8, 10, 10, 3, 8, 7, 5, 4, 0, 7, 5, 0 }, { //捷足先登,1横4竖 32 1, 15, 15, 3, 2, 15, 15, 4, 0, 10, 10, 0, 5, 6, 7, 8, 5, 6, 7, 8 }, { //插翅难飞,2横3竖 62 6, 15, 15, 1, 6, 15, 15, 2, 10, 10, 4, 3, 7, 11, 11, 8, 7, 0, 0, 8 }, { //殊途同归,2横3竖 81 6, 15, 15, 7, 6, 15, 15, 7, 1, 8, 0, 3, 2, 8, 0, 4, 10, 10, 11, 11 }, { //守口如瓶1,2横3竖 81 6, 15, 15, 7, 6, 15, 15, 7, 1, 8, 0, 3, 2, 8, 0, 4, 10, 10, 11, 11 }, { //守口如瓶2,2横3竖 99 2, 15, 15, 4, 6, 15, 15, 7, 6, 8, 0, 7, 2, 8, 0, 4, 10, 10, 11, 11 }, { //双将挡路,2横3竖 73 6, 15, 15, 1, 6, 15, 15, 2, 8, 10, 10, 7, 8, 11, 11, 7, 3, 0, 0, 4 }, { //横马当关,2横3竖 83 6, 15, 15, 7, 6, 15, 15, 7, 10, 10, 11, 11, 3, 8, 0, 4, 2, 8, 0, 1 }, { //层层布防,3横2竖 102 8, 15, 15, 7, 8, 15, 15, 7, 1, 10, 10, 3, 2, 11, 11, 4, 0, 12, 12, 0 }, { //兵将联防,3横2竖 120 1, 15, 15, 3, 8, 15, 15, 7, 8, 10, 10, 7, 2, 11, 11, 4, 0, 12, 12, 0 }, { //兵挡将阻,3横2竖 87 1, 15, 15, 7, 2, 15, 15, 7, 8, 10, 10, 3, 8, 11, 11, 4, 0, 12, 12, 0 }, { //堵塞要道,3横2竖 39 1, 15, 15, 3, 2, 15, 15, 4, 8, 7, 10, 10, 8, 7, 11, 11, 0, 0, 12, 12 }, { //瓮中之鳖,3横2竖 103 8, 15, 15, 7, 8, 15, 15, 7, 10, 10, 11, 11, 1, 12, 12, 3, 2, 0, 0, 4 }, { //层峦叠嶂,3横2竖 98 8, 15, 15, 7, 8, 15, 15, 7, 1, 11, 11, 2, 10, 10, 12, 12, 2, 0, 0, 4 }, { //水泄不通,4横1竖 79 8, 15, 15, 1, 8, 15, 15, 2, 10, 10, 13, 13, 11, 11, 12, 12, 3, 0, 0, 4 }, { //四路进兵,4横1竖 77 1, 15, 15, 3, 2, 15, 15, 4, 8, 0, 10, 10, 8, 0, 11, 11, 13, 13, 12, 12 }, { //入地无门,4横1竖 87 8, 15, 15, 1, 8, 15, 15, 2, 4, 10, 10, 3, 11, 11, 12, 12, 0, 13, 13, 0 }, { //勇闯五关 (调兵遣将),5横0竖 34 1, 15, 15, 3, 2, 15, 15, 4, 10, 10, 11, 11, 12, 12, 13, 13, 0, 14, 14, 0 }, { //四面楚歌,1横4竖 56 5, 1, 2, 7, 5, 15, 15, 7, 3, 15, 15, 8, 6, 10, 10, 8, 6, 0, 0, 4 }, { //前呼后拥,5横0竖 22 1, 2, 15, 15, 14, 14, 15, 15, 13, 13, 11, 11, 12, 12, 10, 10, 0, 0, 3, 4 }, { //兵临曹营,1横4竖 34 1, 15, 15, 3, 2, 15, 15, 4, 8, 10, 10, 7, 8, 5, 6, 7, 0, 5, 6, 0 }, { //五将逼宫,3横2竖 36 10, 10, 12, 12, 8, 15, 15, 7, 8, 15, 15, 7, 1, 11, 11, 4, 2, 0, 0, 3 }, { //前挡后阻,2横3竖 42 15, 15, 10, 10, 15, 15, 6, 1, 8, 7, 6, 3, 8, 7, 2, 4, 0, 11, 11, 0 }, { //近在咫尺,2横3竖 98 1, 8, 6, 7, 2, 8, 6, 7, 10, 10, 3, 4, 11, 11, 15, 15, 0, 0, 15, 15 }, { //走投无路 (传说此局无解) 0横5竖 5, 15, 15, 7, 5, 15, 15, 7, 9, 6, 1, 8, 9, 6, 2, 8, 3, 0, 0, 4 }, { //比翼横空,4横1竖 28 10, 10, 15, 15, 11, 11, 15, 15, 12, 12, 13, 13, 1, 0, 3, 8, 2, 0, 4, 8 }, { //夹道藏兵,4横1竖 75 15, 15, 1, 8, 15, 15, 2, 8, 10, 10, 11, 11, 12, 12, 13, 13, 3, 0, 0, 4 }, { //屯兵东路,1横4竖 71 15, 15, 8, 7, 15, 15, 8, 7, 10, 10, 1, 2, 6, 5, 3, 4, 6, 5, 0, 0 }, { //四将连关,3横2竖 39 15, 15, 10, 10, 15, 15, 11, 11, 8, 7, 12, 12, 8, 7, 1, 2, 3, 0, 0, 4 }, { //峰回路转 (过完一山又一山),2横3竖 138 1, 2, 3, 7, 15, 15, 6, 7, 15, 15, 6, 8, 0, 10, 10, 8, 0, 4, 11, 11 }}; }

测试代码

public class HuaRongDao { public static void main(String args[]) { // ZBD.test(); // ZBD_HX.test(); // int[] qp = { // 2, 0, 5, 5, // 2, 3, 1, 1, // 3, 1, 2, 3, // 1, 0, 3, 1, // 4, 4, 1, 2 // }; // PmHx hx = new PmHx(); // hx.check(qp); // int[] qp = { // 6, 15, 15, 7, // 6, 15, 15, 7, // 8, 11, 11, 5, // 8, 3, 4, 5, // 2, 0, 0, 1 // }; // Solver solver = new Solver(); // solver.bfs(qp, false); // Solver solver1 = new Solver(); // int[] hashLayout = HrdUtil.convertToHashLayout(qp); // solver1.bfs(hashLayout, true); for (int i = 0; i < LocalConst.allLayouts.length; i++) { int[] layout = LocalConst.allLayouts[i]; String layoutName = LocalConst.layoutNames[i]; Solver solver = new Solver(); int num = i+1; System.out.println("layout name: " + layoutName + ", num: " + num); // int[] hashLayout = HrdUtil.convertToHashLayout(layout); // solver.bfs(hashLayout, true); solver.bfs(layout, false); } } }
转载请注明原文地址: https://www.6miu.com/read-850061.html

最新回复(0)