Java 骑士';s循环/递归
我试图学习更多关于递归的知识,但不知怎么的,我无法解决骑士之旅,我希望有人能指出我的逻辑错误Java 骑士';s循环/递归,java,Java,我试图学习更多关于递归的知识,但不知怎么的,我无法解决骑士之旅,我希望有人能指出我的逻辑错误 class main { static int fsize = 5; // board size (5*5) static int board[][] = new int[fsize][fsize]; static int[] move_x = {1, 2, 2, 1, -1, -2, -2, -1}; // possible moves (x-axis) static
class main {
static int fsize = 5; // board size (5*5)
static int board[][] = new int[fsize][fsize];
static int[] move_x = {1, 2, 2, 1, -1, -2, -2, -1}; // possible moves (x-axis)
static int[] move_y = {-2, -1, 1, 2, 2, 1, -1, -2}; // possible moves (y-axis)
// x = current x coordinate
// y = current y coordinate
static void Solve(int move_number, int x, int y) {
board[x][y] = move_number;
// check whether the knight has been on all filds or not
if (move_number == ((fsize * fsize) - 1)) {
for (int i = 0; i < fsize; i++) {
for (int c = 0; c < fsize; c++) {
System.out.printf("%3d", board[i][c]);
}
System.out.println("\n");
}
}
else {
// calculate new board coordinates
for (int i = 0; i < 8; i++) {
for (int c = 0; c < 8; c++) {
// Check whether the new coordinates are valid or not
if ((x + move_x[i]) >= 0 && (x + move_x[i]) < fsize && (y + move_y[c]) >= 0 && (y + move_y[c]) < fsize) {
// check whether the knight has been on this field or not (-1 = hasn't been here)
if (board[x + move_x[i]][y + move_y[c]] == -1) {
System.out.println("Move: " + move_number + "\n");
// Find next field
Solve(move_number + 1, (x + move_x[i]), (y + move_y[c]));
}
}
}
}
// couldn't find a valid move
board[x][y] = -1;
}
}
public static void main(String[] args) {
for (int i = 0; i < fsize; i++) {
for (int c = 0; c < fsize; c++) {
board[i][c] = -1;
}
}
Solve(0, 0, 0);
}
}
主类{
静态int fsize=5;//电路板大小(5*5)
静态int板[][]=新int[fsize][fsize];
static int[]move_x={1,2,2,1,-1,-2,-2,-1};//可能的移动(x轴)
static int[]move_y={-2,-1,1,2,2,1,-1,-2};//可能的移动(y轴)
//x=当前x坐标
//y=当前y坐标
静态无效解算(整数移动_数,整数x,整数y){
板[x][y]=移动编号;
//检查骑士是否在所有场上
if(move_number==((fsize*fsize)-1)){
对于(int i=0;i=0&&(x+move_x[i])=0&(y+move_y[c])
编辑:希望这是好的。我试着运行这个程序,但不能得到超过22个有效的动作。嗯,所以我试了一下,试图弄清楚到底发生了什么。这是我能收集到的
sprung_x
和sprung_y
应该一起移动,因为它们代表骑士的移动。您有c
和i
作为在这些数组上移动的独立索引,但实际上它应该只有1个变量。我敲打内部for
循环,在看到c
的地方使用I
SucheWeg
的末尾,将调用它的单元格重置为-1。这给我带来了无限循环。删除该行允许它在单元格1、2的19个移动中正常完成。根据骑士之旅的定义,即从(0,0)开始的牢房向外移动1次攻击,因此代表一次完整的旅行fsize
(共5个)可能未完成。我用6来代替测试SucheWeg
仍将继续运行,并且需要一种正常终止的方法。如果遇到死胡同(我假设-1重置是从#2开始的),你必须考虑到决策的展开,但也要意识到,如果你不小心,同样的展开将使决策永远进行下去**当您从方法返回时,在撤消步骤之前,应检查电路板是否已满。如果已满,则表示您已到达终点仅向您展示我使用的代码:
static boolean isFull(int b [][])
{
for(int i = 0; i < b.length; i++)
{
for(int k = 0; k < b[i].length; k++)
{
if(b[i][k] == -1) return false;
}
}
return true;
}
static void SucheWeg(int schrittnummer, int x, int y)
{
board[x][y] = schrittnummer;
if(schrittnummer == ((fsize * fsize) - 1)) return;
for(int i = 0; i < 8; i++)
{
int nextX = x + sprung_x[i];
int nextY = y + sprung_y[i];
// if we can visit the square, visit it
if(nextX >= 0 && nextX < fsize && nextY >= 0 && nextY < fsize)
{
if(board[nextX][nextY] == -1)
{
SucheWeg(schrittnummer + 1, nextX, nextY);
}
}
}
if(isFull(board)) return; // this is how we avoid resetting to -1
board[x][y] = -1; // reset if you get this far, so you can try other routes
}
输出为:
00 33 28 17 30 35
27 18 31 34 21 16
32 01 20 29 10 05
19 26 11 06 15 22
02 07 24 13 04 09
25 12 03 08 23 14
我想说最后一件事——该算法的良好实现将捕获无限循环。如果这实际上是作业,您应该修改它,直到您可以在任何大小的板上运行它,而不必担心无限循环。目前,如果没有解决方案,它可能会永远运行。因为它看起来有点像家庭作业问题,我将从一个提示开始
move_x
和move_y
是骑士可能的x,y移动。但是,这些可以单独编制索引(i
和c
)。您可能希望重新考虑这一点。问题是,即使第一次尝试移动成功(导致解决方案),您也在尝试不同的有效移动。我会让函数返回一个布尔值,指定它是否达到了一个解决方案。因此,当您从函数本身调用函数时,您应该只尝试下一个有效移动,如果它返回false
。此外,当您尝试其他移动时,您应该清除上一个移动(因为阵列已更改)
编辑:
class main {
static int fsize = 5; // board size (5*5)
static int board[][] = new int[fsize][fsize];
static int[] move_x = {1, 2, 2, 1, -1, -2, -2, -1}; // possible moves (x-axis)
static int[] move_y = {-2, -1, 1, 2, 2, 1, -1, -2}; // possible moves (y-axis)
// x = current x coordinate
// y = current y coordinate
static boolean solve(int move_number, int x, int y)
{
boolean ret = true;
board[x][y] = move_number;
if(move_number == ((fsize * fsize) - 1))
{
for(int i = 0; i < fsize; i++)
{
for(int c = 0; c < fsize; c++)
{
System.out.printf("%3d", board[i][c]);
}
System.out.println("\n");
}
}
else
{
for(int i = 0; i < 8; i++)
{
if((x + move_x[i]) >= 0 && (x + move_x[i]) < fsize
&& (y + move_y[i]) >= 0
&& (y + move_y[i]) < fsize)
{
if(board[x + move_x[i]][y + move_y[i]] == -1)
{
if (solve(move_number + 1, (x + move_x[i]), (y + move_y[i]))) {
break;
}
}
}
}
ret = false;
board[x][y] = -1;
}
return ret;
}
public static void main(String[] args) {
for (int i = 0; i < fsize; i++) {
for (int c = 0; c < fsize; c++) {
board[i][c] = -1;
}
}
solve(0, 0, 0);
}
我可以通过做两件事来修复您的代码:
- 仅使用
单级循环检查接下来的8种可能性for(int i=0;i<8;i++)
- 为什么这里有两个嵌套循环?你只需要检查这8种可能性,就这样
- 每个级别只有8个移动,而不是64个
- 使
板[x][y]=-1代码>求解中的最后一条语句
- 您希望在不考虑
条件的情况下执行此操作if
- 您有撤消
板[x][y]=移动编号代码>退出此级别之前
- 您希望在不考虑
伪码 现在,这就是你所拥有的:
static void Solve(int move_number, int x, int y) {
board[x][y] = move_number;
if (DONE) {
PRINT;
} else {
for (int i = 0; i < 8; i++) {
for (int c = 0; c < 8; c++) {
ATTEMPT_MOVE(i, c); // doesn't make sense!!!
}
}
board[x][y] = -1; // this doesn't belong here!!!
}
}
static void Solve(int move_number,int x,int y){
板[x][y]=移动编号;
如果(完成){
印刷品;
}否则{
对于(int i=0;i<8;i++){
对于(int c=0;c<8;c++){
尝试移动(i,c);//没有意义!!!
}
}
0 15 20 9 24
19 10 23 14 21
16 1 18 5 8
11 6 3 22 13
static void Solve(int move_number, int x, int y) {
board[x][y] = move_number;
if (DONE) {
PRINT;
} else {
for (int i = 0; i < 8; i++) {
for (int c = 0; c < 8; c++) {
ATTEMPT_MOVE(i, c); // doesn't make sense!!!
}
}
board[x][y] = -1; // this doesn't belong here!!!
}
}
static void Solve(int move_number, int x, int y) {
board[x][y] = move_number;
if (DONE) {
PRINT;
} else {
for (int i = 0; i < 8; i++) {
ATTEMPT_MOVE(i); // now makes more sense!
}
}
board[x][y] = -1; // must undo assignment in first line!
}