Я пытаюсь создать правильную судоку.
Я создал 3 метода для проверки чисел и один для создания судоку.
createSudoku()
пытается создать судоку.
colContainsNumber()
: проверьте, содержит ли столбец случайное число, которое я сгенерировал
rowContainsNumber()
: То же, что и colContainsNumber, только для строки.
squareContainsNumber()
: проверьте, содержит ли блок случайное число.
В createSudoku()
я генерирую случайное число, а с помощью цикла while я продолжаю генерировать новое число до тех пор, пока ни один из «содержащих методов» не вернет true (true для «да, число уже находится в строке и т. д.)
Использование всех методов для создания судоку работает. (Например, если я использую только rowContainsNumber, я получу судоку, где ни одна строка не содержит одинаковое число и т. д.)
Но если я использую все три метода вместе, страница не будет отвечать.
Я попытался изменить порядок методов, которые я вызываю в цикле while, но не более того, потому что методы работают нормально, если я вызываю только один из них.
function createSudoku() {
var sudoku = [
[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]
];
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
//generate a random number between 1 and 9
var randomNumber = Math.floor((Math.random() * 9) + 1);
/*Keep generate a random number, until the square doesn't contain
the number. This is the loop where I'm supposed to use all three
Methods (colContains-, rowContains- and squareContainsNumber) but
the page doesn't respond if I use all three of them. If I only use
one like you can see now, the generation works fine*/
while (squareContainsNumber(sudoku, i, j, randomNumber)) {
randomNumber = Math.floor((Math.random() * 9) + 1);
}
sudoku[i][j] = randomNumber;
solvedSudoku[i][j] = randomNumber;
}
}
return sudoku;
}
function rowContainsNumber(sudoku, col, number) {
for (var i = 0; i < 9; i++) {
if (sudoku[col][i] == number) {
return true;
}
}
return false;
}
function colContainsNumber(sudoku, row, number) {
for (var i = 0; i < 9; i++) {
if (sudoku[i][row] == number) {
return true;
}
}
return false;
}
function squareContainsNumber(sudoku, col, row, number)
{
var minRow, maxRow, minCol, maxCol = 0;
//Check which column the loop is in, then set the min and max column so I
//can get the range of the block
switch (col) {
case 0:
case 1:
case 2:
minCol = 0;
maxCol = 2;
break;
case 3:
case 4:
case 5:
minCol = 3;
maxCol = 5;
break;
case 6:
case 7:
case 8:
minCol = 6;
maxCol = 8;
break;
default:
break;
}
//Check which row the loop is in, then set the min and max row so I
//can get the range of the block
switch (row) {
case 0:
case 1:
case 2:
minRow = 0;
maxRow = 2;
break;
case 3:
case 4:
case 5:
minRow = 3;
maxRow = 5;
break;
case 6:
case 7:
case 8:
minRow = 6;
maxRow = 8;
break;
default:
break;
}
//loop through the square and check If the square contains the random number
for (var i = minRow; i <= maxRow; i++) {
for (var j = minCol; j <= maxCol; j++) {
if (sudoku[i][j] == number)
return true;
}
}
return false;
}
Ожидаемый результат будет правильной судоку, в которой ни одна строка, ни один столбец и ни один квадрат не содержат одинаковое число.
Но, как я уже сказал, страница просто не отвечает, вероятно, потому, что цикл while занимает слишком много времени.
1 ответ
Алгоритм случайного выбора значения ячейки судоку на основе выполнения ограничений, заключающихся в том, чтобы не дублировать существующую цифру в строке, столбце или поле, является неполным. Можно следовать ограничениям, но все же обнаружить, что в пустой ячейке ранее все цифры от 1 до 9 были распределены как соседи в строке, ячейке или поле.
Когда размещенный код достигает этого состояния, он пытается сгенерировать новую случайную цифру для головоломки, не проверяя, возможно ли это. Поскольку это невозможно, страница зависает, поскольку она продолжает пытаться ввести другую случайную цифру, которая не сработает.
Этот фрагмент кода проверяет, что дома (строка, столбец или поле) пустой ячейки действительно содержат неиспользуемую цифру, и повторяет попытку головоломки, если это не так:
var attempts = 0;
function puzzle( sudoku) {
++attempts;
function House() {
this.index = Object.create(null);
}
House.prototype.add = function( n) {
if( this.index[n]) {
return 0;
}
this.index[n] = true;
return n;
};
let houses = [];
for( var i = 0; i < 27; ++i) {
houses [i] = new House();
}
let rowOf = index => Math.floor(index/9);
let colOf = index => index%9;
let boxOf = index => 3 * Math.floor( rowOf( index)/3) + Math.floor( colOf( index)/3);
function randomDigit( index) {
let rowHouse = houses[ rowOf( index)];
let colHouse = houses[ 9 + colOf(index)];
let boxHouse = houses[ 18 + boxOf(index)];
let domain = [1,2,3,4,5,6,7,8,9].reduce( function( array, digit) {
if( !(rowHouse.index[ digit] || colHouse.index[digit] || boxHouse.index[ digit])) {
array.push( digit);
}
return array;
}, []);
let digit = domain.length ? domain[ Math.floor( domain.length * Math.random())] : 0;
if( digit) {
rowHouse.add(digit);
colHouse.add(digit);
boxHouse.add(digit);
}
return digit;
}
var sudoku = [];
for( var index = 0 ; index < 81; ++index) {
let digit = randomDigit( index);
if( digit == 0) {
break;
}
sudoku[ index] = digit;
}
if( sudoku.length == 81) {
return sudoku;
}
return puzzle();
}
const sudoku = puzzle();
console.log( "Attempts = " + attempts);
if( sudoku.length < 81) {
sudoku.push('x');
console.log("invalid sudoku");
}
for( let i = 0; i < 81; i += 9) {
console.log( sudoku.slice( i, i+9).toString());
}
Запуск сниппета показывает, что для получения результата может потребоваться большое количество попыток.
Беглый взгляд в Интернете показывает, что это может быть необычный метод создания завершенной головоломки, и без дополнительного опыта я не могу комментировать его полезность.
Похожие вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript/JS) и его различных диалектах/реализациях (кроме ActionScript). Обратите внимание, что JavaScript — это НЕ Java. Включите все теги, относящиеся к вашему вопросу: например, [node.js], [jQuery], [JSON], [ReactJS], [angular], [ember.js], [vue.js], [typescript], [стройный] и т. д.