递归objective-c void-method的问题

时间:2011-03-13 17:04:23

标签: objective-c recursion return void

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

有人有想法吗?!

这是代码。

- (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;
  }
}

1 个答案:

答案 0 :(得分:0)

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

由于您说您有可用的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;
    }
}