-
背景
先来介绍下孔明棋吧,它是法国跳棋独立钻石在中国的别称,英文叫做“Pegged”。简单介绍下玩法吧,
常见棋盘如下:
走棋规则如下:
图中的黑点为有棋子,白点为无棋子。
-
算法介绍
这个算法其实整个程序不是很难,但是针对程序的设计很容易走弯路,导致算法复杂度增加。初次尝试时,我当时考虑到这一问题,随着棋盘复杂度增加,白点越来越少,因此我把白点作为参考点,然后遍历所有的点,对白点的上下左右进行判断,进而移动。但是这样的话,随着程序的运行,白点越来越多,实际上是增加了时间复杂度。这里正确的做法应该是,对黑点进行处理,也就是以黑点为参考点,进行判断。
初次尝试时,还犯了一个问题,当某次移动后,发现此路不通,那就要返回上一步进行处理。这块我之前的处理方法是,构造一个新的跟当前棋盘一样的棋盘,用它去移动,这样便避免了之后的移动。但是这样的话,申请空间的次数很多,这样实际上还是增加了时间复杂度。其实这里就按照简单的方式,要是此路不通,就把棋再换过来就行了。
这两个问题,导致了程序的时间复杂度很大,自己分析了下,还是因为开始对程序的分析不够。所以,尽管这个程序不是很难,但却让自己感悟很深。
public class PegSolitaire {
public static final int[] MOVEX = {0, 1, 0, -1};
public static final int[] MOVEY = {1, 0, -1, 0};
public static String solve(boolean[][] pegs) {
if(isSolve(pegs)) {
return "";
}
String result = null;
int delti = 0;
int deltj = 0;
for(int i = 0; i < 7; i++) {
for(int j = 0; j < 7; j++) {
if(!iseffectivity(i, j)) {
continue;
}
if(pegs[i][j]) {
for(int k = 0; k < 4; k++) {
delti = MOVEX[k];
deltj = MOVEY[k];
result = tryMove(pegs, i, j, i + delti, j + deltj, i + 2 * delti, j + 2 * deltj);
if(result != null) {
String str = solve(pegs);
if(str != null) {
return result + str;
}
pegs[i][j] = true;
pegs[i + delti][j + deltj] = true;
pegs[i + 2 * delti][j + 2 * deltj] = false;
}
}
}
}
}
return null;
}
private static String tryMove(boolean[][] pegs, int startX, int startY, int jumpX,
int jumpY, int endX, int endY) {
if(jumpX < 0 || jumpY < 0 || endX < 0 || endY < 0) {
return null;
}
if(jumpX >= 7 || jumpY >= 7 || endX >= 7 || endY >= 7) {
return null;
}
if(!iseffectivity(endX, endY)) {
return null;
}
if(pegs[jumpX][jumpY] != true || pegs[endX][endY] != false) {
return null;
}
pegs[startX][startY] = false;
pegs[jumpX][jumpY] = false;
pegs[endX][endY] = true;
StringBuffer str = new StringBuffer();
str.append(startX + " " + startY + " "
+ endX + " " + endY + "\n");
return str.toString();
}
private static boolean iseffectivity(int x, int y) {
if(x < 2 && (y < 2 || y > 4)) {
return false;
}else if(x > 4 && (y < 2 || y > 4)) {
return false;
}else {
return true;
}
}
public static boolean isSolve(boolean[][] board) {
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 7; j++) {
if (board[i][j] && !(i == 3 && j == 3)) {
return false;
}
}
}
return board[3][3];
}
}