递归 Objective-C void-method 的问题

发布于 2024-10-21 21:01:48 字数 1462 浏览 6 评论 0原文

这是我的第一个问题,我希望有人可以帮助我。 我是 iPhone 编程新手,想尝试一个简单的应用程序... 它是一个使用递归方法的 SudokuSolver。在 JAVA 中,这段代码不会产生任何问题,但在 Objective-C 中,当数独被解决时,代码不会停止。它仍在尝试解决数独问题并稍后停止。

有人有想法吗?

这是代码。

- (SudokuSolver *) initWithField: (int[9][9]) field {
self = [super init];
if(self) {
    for (int i=0; i<9; i++) {
        for (int j=0; j<9; j++) {
            sudokuField[i][j] = field[i][j];
            if (field[i][j]) {
                sudokuFieldStatic[i][j] = 1;
            } else {
                sudokuFieldStatic[i][j] = 0;
            }
        }
    }
}
return self;
}

- (void) solve {
   [self solveFieldAtRow:0 andCol:0];
}

- (void) solveFieldAtRow: (int) row andCol: (int) col {
  if (row > 8) {
    return;
  } else {
    while (sudokuField[row][col] != 0) {
        if (++col > 8) {
            col = 0;
            row++;
            if (row > 8) {
                return;
            }
        }
    }
    for (int num=1; num<10; num++) {
        if ([self checkRow:row forNumber:num] && [self checkCol:col forNumber:num] && [self checkFieldAtRow:row andCol:col forNumber:num]) {
            sudokuField[row][col] = num;
            [self showFieldInConsole:0];
            if (col < 8) {
                [self solveFieldAtRow:row andCol:col+1];
            } else {
                [self solveFieldAtRow:row+1 andCol:0];
            }
        }
    }
    sudokuField[row][col] = 0;
  }
}

thats my first question here and i hope someone can help me.
I´m new at the iPhone programming and want to try an easy app...
It´s an SudokuSolver which is working with an recursive Method. In JAVA this code is making no problems, but in Objective-C the code isn´t stopping when Sudoku is solved. It´s still trying to solve the Sudoku and stops later.

Anyone an idea?!

Here´s the code.

- (SudokuSolver *) initWithField: (int[9][9]) field {
self = [super init];
if(self) {
    for (int i=0; i<9; i++) {
        for (int j=0; j<9; j++) {
            sudokuField[i][j] = field[i][j];
            if (field[i][j]) {
                sudokuFieldStatic[i][j] = 1;
            } else {
                sudokuFieldStatic[i][j] = 0;
            }
        }
    }
}
return self;
}

- (void) solve {
   [self solveFieldAtRow:0 andCol:0];
}

- (void) solveFieldAtRow: (int) row andCol: (int) col {
  if (row > 8) {
    return;
  } else {
    while (sudokuField[row][col] != 0) {
        if (++col > 8) {
            col = 0;
            row++;
            if (row > 8) {
                return;
            }
        }
    }
    for (int num=1; num<10; num++) {
        if ([self checkRow:row forNumber:num] && [self checkCol:col forNumber:num] && [self checkFieldAtRow:row andCol:col forNumber:num]) {
            sudokuField[row][col] = num;
            [self showFieldInConsole:0];
            if (col < 8) {
                [self solveFieldAtRow:row andCol:col+1];
            } else {
                [self solveFieldAtRow:row+1 andCol:0];
            }
        }
    }
    sudokuField[row][col] = 0;
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

百善笑为先 2024-10-28 21:01:48

当谜题解决时,代码不会停止,因为您没有在递归调用后检查谜题是否已解决。因此,即使递归调用找到了解决方案,代码也会在找到解决方案后继续执行,直到尝试了所有可能性。

既然你说你有可以运行的 Java 代码,我建议你将 Java 程序的逻辑与此代码进行比较。您可能会发现 Java 代码确实包含这样的测试。


编辑从上面的评论中,我发现您在Java代码中找不到这样的测试,因为当找到解决方案时,您会滥用异常从递归“返回”。正确的方法是让每个递归调用在找到解决方案时返回 true 值,如果没有找到解决方案则返回 false。然后每个步骤都应该检查其子调用是否成功,如果成功则返回成功。像这样的事情:

- (BOOL) solveFieldAtRow: (int) row andCol: (int) col {
    if (row > 8) {
        // reached the end, so it must have succeeded
        return YES;
    } else {
        while (sudokuField[row][col] != 0) {
            if (++col > 8) {
                col = 0;
                row++;
                if (row > 8) {
                    // reached the end, so it must have succeeded
                    return YES;
                }
            }
        }
        for (int num=1; num<10; num++) {
            if ([self checkRow:row forNumber:num] && [self checkCol:col forNumber:num] && [self checkFieldAtRow:row andCol:col forNumber:num]) {
                sudokuField[row][col] = num;
                [self showFieldInConsole:0];
                BOOL result;
                if (col < 8) {
                    result = [self solveFieldAtRow:row andCol:col+1];
                } else {
                    result = [self solveFieldAtRow:row+1 andCol:0];
                }
                if (result) {
                    // Our child call succeeded, so we pass that back up
                    // the stack.
                    return YES;
                }
            }
        }
        sudokuField[row][col] = 0;
        // If we get here, we could not find a solution. Return failure
        // back up the stack.
        return NO;
    }
}

The code isn't stopping when the puzzle is solved because you don't check whether the puzzle is solved after the recursive call. So even if the recursive call found a solution, the code just continues on even after finding a solution until it has tried every possibility.

Since you say you have Java code that works, I suggest you compare the logic of the Java program versus this code. You'll probably find the Java code does include such a test.


Edit From your comment above, I see that you won't find such a test in your Java code, because there you are abusing exceptions to "return" from the recursion when a solution is found. The proper way is to have each recursive call return a true value if it found a solution and false if it didn't. And then each step should check if its child call succeeded, and itself return success if so. Something like this:

- (BOOL) solveFieldAtRow: (int) row andCol: (int) col {
    if (row > 8) {
        // reached the end, so it must have succeeded
        return YES;
    } else {
        while (sudokuField[row][col] != 0) {
            if (++col > 8) {
                col = 0;
                row++;
                if (row > 8) {
                    // reached the end, so it must have succeeded
                    return YES;
                }
            }
        }
        for (int num=1; num<10; num++) {
            if ([self checkRow:row forNumber:num] && [self checkCol:col forNumber:num] && [self checkFieldAtRow:row andCol:col forNumber:num]) {
                sudokuField[row][col] = num;
                [self showFieldInConsole:0];
                BOOL result;
                if (col < 8) {
                    result = [self solveFieldAtRow:row andCol:col+1];
                } else {
                    result = [self solveFieldAtRow:row+1 andCol:0];
                }
                if (result) {
                    // Our child call succeeded, so we pass that back up
                    // the stack.
                    return YES;
                }
            }
        }
        sudokuField[row][col] = 0;
        // If we get here, we could not find a solution. Return failure
        // back up the stack.
        return NO;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文