我正在尝试创建正确的数独。
我创建了3种方法来检查数字,一种方法是生成数独。
createSudoku()
尝试创建一个数独。
colContainsNumber()
:检查col是否包含我生成的随机数
rowContainsNumber()
:与colContainsNumber相同,仅用于行
squareContainsNumber()
:检查一个块是否包含随机数。
在createSudoku()
中,我生成一个随机数,并使用while循环不断生成一个新数,直到“ contain-Methods”均未返回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循环花费的时间太长了。
答案 0 :(得分:0)
基于不重复复制行,列或框中现有数字的约束条件,随机选择数独单元格值的算法不完整。人们可能会遵循这些约束条件,但仍然会发现一个空单元格之前已将所有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());
}
运行该代码段表明,可能需要进行大量尝试才能获得结果。
在网上快速浏览表明,这可能是生成完整拼图的一种不寻常的方法,如果没有进一步的经验,我无法评论其用途。