孔明棋算法

  • 背景

先来介绍下孔明棋吧,它是法国跳棋独立钻石在中国的别称,英文叫做“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];
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值