Witam, jest ktoś w stanie pomóc? Napisałem algorytm, który w jakimś stopniu działa. Otóż kiedy mam całą tablicę wypełnioną zerami, to generuje sudoku w miarę dobrze. Co jakiś czas wywali undefined (wszystko opisane w kodzie). Nadal nad tym pracuję.
Problem jest inny i występuje wtedy, kiedy użytkownik poda już jakieś liczby, które są poprawne. Do tego mam 2 tablice. Jedna, która trzyma w sobie oryginał liczb wraz z zerami, a druga jest kopią, w której jest undefined zamiast zer (o tym potem). Tutaj głównym warunkiem jest
if(grid[i][j] === undefined) //grid, to kopia
Jeżeli nie ma liczby, to ją dodajemy w innym wypadku przechodzimy do pola dalej.
Originał przyda się w przypadku kiedy zadna liczba nie pasuje i się cofamy o jedno pole. Wtedy sprawdzam, czy liczba, która się tam znajduje jest w oryginale. Jeśli tak to jej NIE ZMIENIAM i cofam się jeszcze jedno pole do tyłu. To ma prawo działać? Kod poniżej (opisany po angielsku, bo wrzucałem tez na overflowa).
var originalGrid = [ //originalGrid
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
],
grid = createCopy(), //copy of iriginalGrid (undefined instead of 0)
invalidGrid = [ //grid for used numbers (I dont want to use the number that was already used in the field)
[[], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], []]
],
supplyGrid = [1, 2, 3, 4, 5, 6, 7, 8, 9], //grid with numbers
row = 0,
col = 0,
value = 0,
index = 0,
backward = false,
z = 1;
function createCopy() { //create copy of original grid
var copyGrid = [9];
for (var i = 0; i < 9; i++) {
copyGrid[i] = []
for (j = 0; j < 9; j++) {
if (originalGrid[i][j] === 0) {
copyGrid[i][j] = undefined; //put undefined instead of 0
} else {
copyGrid[i][j] = originalGrid[i][j];
}
}
}
return copyGrid;
}
var solveSudoku = function (grid, row, col) { //solver
if (row > 7 && col > 8) return; //end function when it reaches the end
if (col > 8) {
row++;
col = 0;
}
if (grid[row][col] === undefined) { //if there's no number
index = Math.floor(Math.random() * supplyGrid.length);
value = supplyGrid[index];
if (isValid(row, col, value)) { //validate row, col and box
grid[row][col] = value; //assigns the value
if (backward) { //checking if the algorithm went back to change the previous value
z = 1;
backward = false;
};
var iArr = invalidGrid[row][col];
iArr.push(value)
col++; //if value is fine, increase column by 1
supplyGrid = [1, 2, 3, 4, 5, 6, 7, 8, 9]; //reset supply gird
solveSudoku(grid, row, col);
} else { //if the number is invalid (cannot be placed in a row, column or box)
supplyGrid.splice(index, 1); //delete the number from supply grid. I dont want to use the same value again in the same field.
//console.log(supplyGrid);
if (supplyGrid.length < 1) { //if there's no number left (all numbers are invalid for this field)
changePreviousValue(grid, row, col); //go back to the previous field
}
solveSudoku(grid, row, col);
}
} else { //if number exist in this field
col++; //increase the col value
solveSudoku(grid, row, col);
}
return this;
}
function changePreviousValue(grid, row, col) {
// var lastRowIndex = row;
// var lastColIndex = col;
col--; //go back one field
if (col < 0) {
col = 8;
row--;
}
if (originalGrid[row][col] === grid[row][col]) { //here im checking the value in this field. If it's in originalGrid that means I dont want to do anything with it. I dont want to change that number.
changePreviousValue(grid, row, col); // callin function again with decreased col value (so we went back by 2 field)
z++;
}
backward = true;
if (z > 1) { //whether the algorithm went back by at least 2 fields
if (col > 7) {
row++;
col = -1;
}
var iArr = invalidGrid[row][col + 1];
iArr.splice(0, invalidGrid[row][col + 1].length); //delete used values in the next field.
}
z++;
supplyGrid = [1, 2, 3, 4, 5, 6, 7, 8, 9]; //reset supply grid
//col = -1;
for (var i = 0; i < invalidGrid[row][col].length; i++) {
supplyGrid.splice(supplyGrid.indexOf(invalidGrid[row][col][i]), 1) //here im getting UNDEFINED sometimes. Its resposible for deleting used numbers in ACTUAL field. f.e I used 6 before, in the next field it couldn't fit any number so it went back to the same field. I dont want use 6 again cuz it wasnt working.
}
grid[row][col] = undefined; //set field value to undefined, so we can assign new number.
solveSudoku(grid, row, col);
}
function displaySudoku() {
var string = '';
for (var i = 0; i < 9; i++) {
string += '<tr>';
for (var j = 0; j < 9; j++) {
string += '<td>';
string += `${grid[i][j]}`;
string += '</td>';
}
string += '</tr>';
}
document.write('<table>' + string + '</table>')
}
function isValid(row, col, value) {
if ((validateColumn(row, col, value)) || (validateRow(row, col, value)) || (validateBox(row, col, value))) {
return false;
} else {
return true;
}
}
function validateBox(row, col, value) {
row = Math.floor(row / 3) * 3;
col = Math.floor(col / 3) * 3;
var isFound = false;
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (grid[row + i][col + j] == value) isFound = true;
}
}
return isFound;
}
function validateRow(row, col, value) {
var isFound = false;
for (var i = 0; i < 9; i++) {
if (grid[row][i] === value) isFound = true;
}
return isFound;
}
function validateColumn(row, col, value) {
var isFound = false;
for (var i = 0; i < 9; i++) {
if (grid[i][col] === value) isFound = true;
}
return isFound;
}