Я пишу рекурсивный решатель для головоломки Судоку. Я храню пустые места с нулями, чтобы моя программа могла их легче читать. У меня есть оригинальная головоломка, начиная с нижнего индекса, чтобы лучше визуализировать сетку. Я не уверен, что у меня есть полное представление о рекурсии, и в этом проблема. Я получаю вывод, который, кажется, на пути к разгадке головоломки, но он оставляет там нули, которых не должно быть. Я думаю, что это как-то связано с размещением моего unsetSquare или с операторами return.
Вот пример вывода …
**************************************************
7 4 3 | 8 2 1 | 5 6 8
2 6 8 | 0 9 0 | 0 1 0
0 0 0 | 0 0 6 | 0 0 4
---------|---------|---------
0 0 0 | 0 0 0 | 2 3 9
0 0 0 | 0 0 0 | 0 0 0
4 1 5 | 0 0 0 | 0 0 0
---------|---------|---------
9 0 0 | 5 0 0 | 0 0 0
0 2 0 | 0 1 0 | 7 4 0
0 0 0 | 2 0 0 | 9 0 5
**************************************************
**************************************************
7 4 3 | 8 2 1 | 5 6 9
2 6 8 | 0 9 0 | 0 1 0
0 0 0 | 0 0 6 | 0 0 4
---------|---------|---------
0 0 0 | 0 0 0 | 2 3 9
0 0 0 | 0 0 0 | 0 0 0
4 1 5 | 0 0 0 | 0 0 0
---------|---------|---------
9 0 0 | 5 0 0 | 0 0 0
0 2 0 | 0 1 0 | 7 4 0
0 0 0 | 2 0 0 | 9 0 5
**************************************************
**************************************************
7 4 3 | 8 2 1 | 5 6 0
2 6 8 | 1 9 0 | 0 1 0
0 0 0 | 0 0 6 | 0 0 4
---------|---------|---------
0 0 0 | 0 0 0 | 2 3 9
0 0 0 | 0 0 0 | 0 0 0
4 1 5 | 0 0 0 | 0 0 0
---------|---------|---------
9 0 0 | 5 0 0 | 0 0 0
0 2 0 | 0 1 0 | 7 4 0
0 0 0 | 2 0 0 | 9 0 5
**************************************************
**************************************************
7 4 3 | 8 2 1 | 5 6 0
2 6 8 | 2 9 0 | 0 1 0
0 0 0 | 0 0 6 | 0 0 4
---------|---------|---------
0 0 0 | 0 0 0 | 2 3 9
0 0 0 | 0 0 0 | 0 0 0
4 1 5 | 0 0 0 | 0 0 0
---------|---------|---------
9 0 0 | 5 0 0 | 0 0 0
0 2 0 | 0 1 0 | 7 4 0
0 0 0 | 2 0 0 | 9 0 5
**************************************************
**************************************************
7 4 3 | 8 2 1 | 5 6 0
2 6 8 | 3 9 0 | 0 1 0
0 0 0 | 0 0 6 | 0 0 4
---------|---------|---------
0 0 0 | 0 0 0 | 2 3 9
0 0 0 | 0 0 0 | 0 0 0
4 1 5 | 0 0 0 | 0 0 0
---------|---------|---------
9 0 0 | 5 0 0 | 0 0 0
0 2 0 | 0 1 0 | 7 4 0
0 0 0 | 2 0 0 | 9 0 5
**************************************************
Обратите внимание, что в конце первой строки, он переходит к 8 в поисках решения, затем к 9, 9 не является допустимым, и он достиг конца цикла for, поэтому он заменяет его на ноль и продолжает. Как я могу заставить его вернуться к другим цифрам в первом ряду, чтобы получить более полное решение?
Вот моя функция рекурсии …
bool DoTheWork::addSquare(int& depth, ostream& outStream){
for(int i = ONE; i <= NINE; ++i){
for(int j = ONE; j <= NINE; ++j){
if(i == NINE && j == NINE && board.getSquare(NINE, NINE) != ZERO){
cout << i << " " << j << endl;
return true;
}
//cout << "original" << board.getSquare(i, j) << "coord: " << i << ", " << j << endl;
if(board.getSquare(i, j) == ZERO){
//cout << "original: " << board.getSquare(i, j) << "coord: " << i << ", " << j << endl;
for(int k = ONE; k <= NINE; ++k){
board.setSquare(i, j, k);
board.display(outStream);
if(board.isLegal()){
return addSquare(depth, outStream);
}
else{
board.unsetSquare(i, j);
}
}
}
}
}
board.display(outStream);
return false;
}
Я вижу проблему:
Так должно быть:
if(board.isLegal()){
if( addSquare(depth, outStream))
return true;
}
Значит, если вся доска решена, тогда откат.
РЕДАКТИРОВАТЬ думаю об этом:
Вы ставите 1 в первом квадрате, он возвращает ложь. ты не хочешь попробовать поставить 2?
EDIT2
Больше проблем:
if(i == NINE && j == NINE && board.getSquare(NINE, NINE) != ZERO){
cout << i << " " << j << endl;
return true;
}
Предполагается, что это проверка завершения? Вы проверяете только 1 кв. и в вашем образце он заполнен!
вам нужно проверить, что нет 0.
EDIT3:
bool DoTheWork::addSquare(int& depth, ostream& outStream){
//use flag to let you know if all completed
bool zeroFound = false;
for(int i = ONE; i <= NINE; ++i){
for(int j = ONE; j <= NINE; ++j){
//cout << "original" << board.getSquare(i, j) << "coord: " << i << ", " << j << endl;
if(board.getSquare(i, j) == ZERO){
zeroFound = true;
//cout << "original: " << board.getSquare(i, j) << "coord: " << i << ", " << j << endl;
for(int k = ONE; k <= NINE; ++k){
board.setSquare(i, j, k);
board.display(outStream);
if(board.isLegal()){
if(addSquare(depth, outStream)){
return true;
}
else{
board.unsetSquare(i, j);
}
}
}
}
}
}
board.display(outStream);
return !zeroFound; //true in case it is full!
}
Оказывается, у меня было что-то не в том порядке, а не в нужном объеме. После успешного выполнения этого с циклом while, я нашел решение с помощью цикла for.
bool DoTheWork::addSquare(int& depth, ostream& outStream){
for(int i = 1; i < 10; ++i){
for(int j = 1; j < 10; ++j){
if(board.getSquare(i, j) == 0){
if(i == 10){
return true;
}
for(int k = 1; k <= 9; ++k){
board.setSquare(i, j, k);
if(board.isLegal() && addSquare(depth, outStream)){
return true;
}
}
board.unsetSquare(i, j);
return false;
}
}
}
}