我一直在尝试制作一个使用Javascript随机创建Sudoku的程序。我在Atom中同时包含了代码和该代码的图片,以使其更具可读性。
基本上从16-20行开始,我在行中添加了9个数字,然后将它们混洗并将结果存储在newRow中。
从第25行开始,我开始一个循环,遍历所有过去的行,这些行存储在名为“ actualRow”的数组中。因此,将行改组为newRow,将newRow存储在actualRow中。从第二个newRow开始,我要检查是否有重复的值。这就是为什么我启动loop1和loop2的原因。 Loop1遍历所有先前的行,而其中的loop2遍历所有值。
if语句旨在捕获重复项,但永远不会求值为true,显然应该这样做,因为总是有很多重复项。如果为true,则error = true,因此我不会在实际行中添加特定的newRow ,但请重新开始循环,直到没有重复为止。
因此,真正的问题出在第32行的if语句中。我在这里错过了什么?
<script>
var row = [];
var newRow = [];
var actualRow = [];
var mistake;
function makeSudoku() {
for (var j = 0; j < 9; j++) {
row = [1,2,3,4,5,6,7,8,9];
newRow = [];
mistake = false;
for (var i = 1; i < 10; i++) {
newRow.push( row.splice( Math.floor( Math.random() * row.length) , 1) );
}
if ( j !== 0) { // no need to check for duplicates in first row
loop1:
for (var k = j-1; k > -1 ; k--) { // for every row that came before..
loop2:
for (var l = 0; l < 9; l++) { // for every value in that row..
if ( actualRow[j-1][l] == newRow[l] ) { // issue here!!!
mistake = true;
console.log("duplicate row value");
} else {
console.log("Why does this if statement always evaluate to else?");
}
}
}
}
if ( mistake == false) {
actualRow.push(newRow);
} else if ( mistake == true) {
j -= 1;
} else {
}
}
console.log(actualRow);
}
makeSudoku();
最佳答案
您的主要问题在于此行:
newRow.push( row.splice( Math.floor( Math.random() * row.length) , 1) );
这将构建一个数组,但不是数字数组,而是一个单元素数组!以后进行比较时,总会得出false,并说明了为什么总是进入
else
部分。原因在于
splice
方法的工作方式。即使仅提取一个元素,它也会返回一个数组。解决方案是,从您从splice
获得的数组中“解包”值: newRow.push( row.splice( Math.floor( Math.random() * row.length) , 1)[0] );
现在可以使用,但是请注意您的算法效率很低。生成最后一行时,将需要进行多次尝试才能使其正确,因为最后一行仅允许一个排列。这使您的代码迭代了数千次,试图通过纯随机改组使其正确。