2011-03-13 13 views
1

ここに私の最初の質問があり、私は誰かが私を助けることを願っています。 私はiPhoneプログラミングの新機能で、簡単なアプリを試してみたいと思っています。 これは再帰的メソッドで動作しているSudokuSolverです。 Javaではこのコードは問題ありませんが、Objective-Cでは数独が解決されたときにコードが停止することはありません。それはまだ数独を解決しようとしており、後で止まります。再帰的な目的-c voidメソッドの問題

誰かアイデアか。

ここにコードがあります。

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

あなたは 'sudokuField'の宣言と初期化を共有できますか? – mvds

+0

いくつかのコードはここにはないので、クイックチェックとして:コンパイラの警告が出ますか? 'checkRow'などで問題が発生した場合。常にゼロ以外の値を返すと、解決するまでに時間がかかることがあります。 – mvds

+0

再帰パターンはあまり明確ではありません。 'row> = 9 ||これを書き換えることをお勧めします。 'solveFieldAtRow'メソッドの開始時にcol> = 8'チェックを行います。 –

答えて

0

再帰呼び出し後にパズルが解決されたかどうかをチェックしないため、パズルが解決されたときにコードは停止しません。たとえ再帰呼び出しが解を見つけたとしても、コードはあらゆる可能性を試してみるまで解を見つけた後でもそのまま続く。

あなたはJavaコードが動作すると言いますから、このコードとJavaプログラムのロジックを比較することをお勧めします。おそらく、Javaコードにこのようなテストが含まれていることがわかります。


編集上記のあなたのコメントから、私は解決策が見つかったときにそこにあなたが再帰から「戻り」の例外を乱用しているので、あなたが、あなたのJavaコードに、このようなテストを見つけることができませんことを参照してください。適切な方法は、各再帰呼び出しが解を見つけた場合は真の値を返し、そうでなければ偽を返すようにすることです。そして、各ステップはその子呼び出しが成功したかどうかをチェックしなければなりません。このようなもの:

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

私は "if(row> 8)return"がその仕事をすると思っていました。 – HMMurdoc

+0

最後に到達したことを検出すると、最終的な再帰呼び出しから戻ります。しかし最後から2番目の再帰呼び出しでは、その最終再帰呼び出しが成功したかどうか、つまりソリューションを見つけることができなかったかどうかはチェックされないため、失敗したものと見なして次の番号を試します。 – Anomie

+0

私は上記のあなたのコメントに照らして、私はあなたが "例外を使って" Javaバージョンをコード化したという私の答えを編集しました。 – Anomie