#javascript
#javascript
Вопрос:
// global variable
// accessible to all functions
var sol =
[[0, 7, 0, 2, 3, 8, 0, 0, 0],
[0, 0, 0, 7, 4, 0, 8, 0, 9],
[0, 6, 8, 1, 0, 9, 0, 0, 2],
[0, 3, 5, 4, 0, 0, 0, 0, 8],
[6, 0, 7, 8, 0, 2, 5, 0, 1],
[8, 0, 0, 0, 0, 5, 7, 6, 0],
[2, 0, 0, 6, 0, 3, 1, 9, 0],
[7, 0, 9, 0, 2, 1, 0, 0, 0],
[0, 0, 0, 9, 7, 4, 0, 8, 0]];
//this function prints the board
var printBoard = function () {
for (let row = 0; row < sol.length; row = 1) {
for (let col = 0; col < sol[row].length; col = 1) {
let id = 'r' (row 1) (col 1);
let elem = document.getElementById(id);
elem.innerHTML = sol[row][col];
}
}
};
function isValid(sol, row, col, k) {
for (let i = 0; i < 9; i ) {
const m = 3 * Math.floor(row / 3) Math.floor(i / 3);
const n = 3 * Math.floor(col / 3) i % 3;
if (sol[row][i] == k || sol[i][col] == k || sol[m][n] == k) {
return false;
}
}
return true;
}
var solve = function() {
for (let row = 0; row < 9; row ) {
for (let col = 0; col < 9; col ) {
if (sol[row][col] == 0) {
for (let k = 1; k <= 9; k ) {
if (isValid(sol, row, col, k) == true) {
sol[row][col] == '${k}';
if(solve() == true) {
return true;
} else {
sol[row][col] == 0;
}
}
}
return false;
}
}
}
return true;
}
printBoard();
У меня возникли проблемы с отладкой этого. Я продолжаю получать сообщение об ошибке, когда нажимаю на кнопку «Решить», которая будет использовать сетку и завершит головоломку судоку: «Ошибка неперехваченного диапазона: превышен максимальный размер стека вызовов». Глядя на файл, кажется, что моя функция isValid() вызывает проблемы здесь. Я думаю, что я где-то застрял в непрерывном цикле? Любая помощь будет оценена. В нем также говорится, что ошибка находится в строках 40 и 24, которые:
function isValid(sol, row, col, k) {
и
if (isValid(sol, row, col, k) == true) {
Пожалуйста, помогите, так как я даже не специалист по CS, и это требование класса, и я не совсем разбираюсь в подобных вещах. Я пытался искать помощь в других ресурсах, но это еще больше сбивает меня с толку.
Редактировать:
//global variable
//accesible to all functions
var sol =
[[0, 7, 0, 2, 3, 8, 0, 0, 0],
[0, 0, 0, 7, 4, 0, 8, 0, 9],
[0, 6, 8, 1, 0, 9, 0, 0, 2],
[0, 3, 5, 4, 0, 0, 0, 0, 8],
[6, 0, 7, 8, 0, 2, 5, 0, 1],
[8, 0, 0, 0, 0, 5, 7, 6, 0],
[2, 0, 0, 6, 0, 3, 1, 9, 0],
[7, 0, 9, 0, 2, 1, 0, 0, 0],
[0, 0, 0, 9, 7, 4, 0, 8, 0]];
//this function prints the board
var printBoard = function () {
for (let row = 0; row < sol.length; row = 1) {
for (let col = 0; col < sol[row].length; col = 1) {
let id = 'r' (row 1) (col 1);
let elem = document.getElementById(id);
elem.innerHTML = sol[row][col];
}
}
};
function isValid(sol, row, col, k) {
for (let i = 0; i < 9; i ) {
const m = 3 * Math.floor(row / 3) Math.floor(i / 3);
const n = 3 * Math.floor(col / 3) i % 3;
if (sol[row][i] == k || sol[i][col] == k || sol[m][n] == k) {
return false;
}
}
return true;
}
var solve = function(sol) {
for (let row = 0; row < 9; row ) {
for (let col = 0; col < 9; col ) {
if (sol[row][col] == 0) {
//set the check for the row and column
for (let k = 1; k <= 9; k ) {
if (isValid(sol, row, col, k) == true) {
sol[row][col] == k;
//check if its not true, then check the row and column again
if(solve() == true) {
return true;
} else {
sol[row][col] = 0;
}
}
}
return false;
}
}
}
return true;
};
printBoard();
Комментарии:
1. Я думаю, проблема в том, что isValid() вызывается несколько раз, и каждый раз, когда он запускается, он повторяется 9 раз.
2. есть способ это исправить? Я полностью потерян
3. Проблема в том, что вы рекурсивно вызываете
solve()
функцию. Каждый раз, когда вы вызываете функцию, она увеличивает стек, и каждый раз, когда функция завершает работу, стек уменьшается. Возможно, вам потребуется немного переработать свой алгоритм, чтобы уменьшить количество рекурсивных вызовов.4. Мне кажется, что вы пытаетесь перебрать судоку. Количество комбинаций будет огромным, намного больше, чем может обработать стек. Как сказал @Luka, преобразование вашей рекурсии в использование цикла устранит рекурсию
Ответ №1:
Вы никогда не меняетесь sol
перед повторным рекурсивным вызовом solve()
.
if (isValid(sol, row, col, k) == true) {
sol[row][col] == '${k}'; // <- does not update sol
if(solve() == true) {
return true;
} else {
sol[row][col] == 0; // <- does not update sol
}
}
Когда вы обнаружите, что параметр для k
этого является допустимым, вы должны обновить sol
его перед повторным вызовом solve()
. В противном случае вы создадите бесконечный рекурсивный цикл, который в конечном итоге превысит максимальный размер стека и приведет к получению ошибки.
Используйте оператор присваивания ( =
) вместо оператора равенства ( ==
) для присвоения нового значения. Кроме '${k}'
того, это приведет к буквальному ${k}
использованию backticks ( `
), если вы хотите использовать интерполяцию строк. Я не вижу причин использовать здесь строку, достаточно простого присвоения k
.
if (isValid(sol, row, col, k) == true) {
sol[row][col] = k; // <- assign k to a cell in the matrix
if(solve() == true) {
return true;
} else {
sol[row][col] = 0; // <- reset the cell back to 0 if it cannot be solved
}
}
Я бы также предложил использовать защитные предложения. Вместо того, чтобы вкладывать все тело цикла for в оператор if, используйте защиту и переходите к следующей итерации с помощью continue
:
for (...) {
if (check) {
// code
}
}
Может быть изменен на:
for (...) {
if (!check) continue;
// code
}
Это обычно улучшает отступы и удобочитаемость кода.
Комментарии:
1. Большое вам спасибо! Мой новый код находится в редактировании, но теперь, когда я нажимаю на кнопку Решить, он ничего не выводит. Какие-нибудь советы?
2. 1. Ваша отредактированная версия по-прежнему использует
sol[row][col] == k
, а неsol[row][col] = k
2. Вы проверили результат сconsole.log(sol)
помощью илиconsole.table(sol)
? Отсутствие вывода в HTML может быть другой проблемой.