初始正方形中的带圆圈的数字是可以移动到沿着行的其他正方形的标记。 在拼图的每个步骤,可以移动标记的正方形中由当前占据的整数指示的方格数。 标记可以沿着该行向左或向右移动,但可以不移动经过任一端。 例如,唯一合法的第一步是将标记向右移动三个方格,因为没有空间向左移动三个空格。
拼图的目标是将标记移动到行的远端的0。
要求: 用递归 或 栈或者队列实现编程。
如果圆圈能够移动到最后0的位置,返回true,否则返回false。
程序要适应任何大小的方格数,并且方格里的数字是随机的,范围是[1,9]。
如何检测不能解决的结构,是否存在可以改善执行时间的方法。
程序运行,需要输入随机的方格数,然后打印出方格,再打印详细的移动路径。
public class PuzzleService {
public static void main(String[] args) {
// 这个ar数组是题目上的数字
//int[] ar = {4,8,5,2,4,5,1,6,1,0};
// 这里是随机产生的ar数组
int[] ar = new int[10];
Random rd = new Random();
for (int i = 0; i < 9; i++) {
ar[i] = rd.nextInt(9)+1;
}
ar[9] = 0;
int[] x = new int[10];// x是记录移动路径信息的数组
Arrays.fill(x, -1); // 把数组所有元素位置都初始化为0
// 寻找路径移动信息
if(!func(ar, 0, x)){
System.out.println("不存在路径");
} else {
// 打印路径信息
backstrace(x, ar, ar.length-1);
}
// 下面两行是辅助打印信息
System.out.println(Arrays.toString(ar));
System.out.println(Arrays.toString(x));
}
/**
* 打印最终的路径移动信息
* @param x
* @param ar
* @param index
*/
private static void backstrace(int[] x, int[] ar, int index) {
if(index == 0) {
System.out.println("数组位置:" + index + "数字:" + ar[index]);
return;
}
backstrace(x, ar, x[index]);
System.out.println("数组位置:" + index + "数字:" + ar[index]);
}
/**
* 递归实现求puzzle路径信息
* @param ar
* @param i
* @param x:存储路径的移动信息
* @return: 找到路径信息返回true,否则返回false
*/
private static boolean func(int[] ar, int i, int[] x) {
// 递归条件结束,找到最后一个0号元素
if(i == ar.length-1){
return true;
}
// 往当前位置的右边走
if(i+ar[i] <= ar.length-1){
if(x[i+ar[i]] == i){ // 表示已经往这个位置走过了,直接返回false
return false;
}
x[i+ar[i]] = i;
if(func(ar, i+ar[i], x)){
return true;
}
}
// 往当前位置的左边走
if(i-ar[i] >= 0){
if(x[i-ar[i]] == i){ // 表示已经往这个位置走过了,直接返回false
return false;
}
x[i-ar[i]] = i;
if(func(ar, i-ar[i], x)){
return true;
}
}
return false; // 表示当前位置i往两边都走不通了,返回false
}
}