如何在 javascript 中的数独生成器中重置函数的随机性
How to reset randomness in a function in a sudoku generator in javascript
我正在构建一个具有随机性的数独生成器。在我的代码中,有一个生成该数独的函数。问题是我无法让两个数独不同
我尝试了 运行 两次该函数,但正如预期的那样,生成的两个数独完全相同。我希望当我复制整个函数并将其粘贴到下面时,数独会有所不同,但这样代码就会太多。
这是我的数独生成函数,为了让您更好地理解代码的作用,我添加了一些注释:
let 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],
];
let sudoku2 = JSON.parse(JSON.stringify(sudoku));
let changesMade = false;
let fields = [];
let counter = 0;
let sudoku3;
window.onload = function () {
generateRandomSudoku(25);
print_sudoku(sudoku3, "table1");
print_sudoku(sudoku, "table2");
// this is the code I used to generate the function twice
generateRandomSudoku(25);
print_sudoku(sudoku3, "table3");
print_sudoku(sudoku, "table4");
};
// solves a sudoku
function solveSudoku() {
fill_possible_fields();
changesMade = false;
counter = 0;
while (!sudoku_complete()) {
counter++;
test_rows_and_cols();
test_blocks();
test_possible_fields();
if (!changesMade) {
break;
} else {
changesMade = false;
}
if (counter === 100) {
break;
}
}
}
// returns true if there are two equal numbers in the same row
function duplicateNumberInRow(s, fieldY) {
numbers = new Array();
for (var i = 0; i < 9; i++) {
if (s[i][fieldY] !== 0) {
if (numbers.includes(s[i][fieldY])) {
return true;
} else {
numbers.push(s[i][fieldY]);
}
}
}
return false;
}
// returns true if there are two equal numbers in the same col
function duplicateNumberInCol(s, fieldX) {
numbers = new Array();
for (var i = 0; i < 9; i++) {
if (s[fieldX][i] !== 0) {
if (numbers.includes(s[fieldX][i])) {
return true;
} else {
numbers.push(s[fieldX][i]);
}
}
}
return false;
}
// returns true if there are two equal numbers in the same box
function duplicateNumberInBox(s, fieldX, fieldY) {
boxX = Math.floor(fieldX / 3);
boxY = Math.floor(fieldY / 3);
numbers = new Array();
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
x = i + 3 * boxX;
y = j + 3 * boxY;
if (s[x][y] !== 0) {
if (numbers.includes(s[x][y])) {
return true;
} else {
numbers.push(s[x][y]);
}
}
}
}
return false;
}
// returns true if there are two equal numbers in the same row, col or box
function duplicateNumberExists(s, fieldX, fieldY) {
if (duplicateNumberInRow(s, fieldY)) {
return true;
}
if (duplicateNumberInCol(s, fieldX)) {
return true;
}
if (duplicateNumberInBox(s, fieldX, fieldY)) {
return true;
}
return false;
}
// generates a random sudoku with a given amount of numbers in it
function generateRandomSudoku(numbers) {
while (!sudoku_complete() || sudoku_invalid(sudoku)) {
// new empty sudoku
sudoku3 = [
[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],
];
sudoku = JSON.parse(JSON.stringify(sudoku3));
// how many numbers are entered already?
let numbersDone = 0;
while (numbersDone < numbers) {
let fieldX = Math.floor(Math.random() * 9);
let fieldY = Math.floor(Math.random() * 9);
let number = Math.floor(Math.random() * 9) + 1;
//alert("" + fieldX + " " + fieldY + " " + number);
if (sudoku3[fieldX][fieldY] === 0) {
sudoku3[fieldX][fieldY] = number;
if (duplicateNumberExists(sudoku3, fieldX, fieldY)) {
sudoku3[fieldX][fieldY] = 0;
continue;
} else {
numbersDone++;
}
//alert("" + numbersDone);
}
}
sudoku = JSON.parse(JSON.stringify(sudoku3));
solveSudoku();
}
}
// fills the possible numbers for the fields
function fill_possible_fields() {
for (var i = 0; i < 9; i++) {
fields[i] = [];
}
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
fields[i][j] = [];
}
}
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
for (var k = 0; k < 9; k++) {
fields[i][j][k] = k + 1;
}
}
}
}
// show the sudoku as a table
function print_sudoku(s, position) {
var tbl = document.createElement("table");
// tbl.style.width = "500px"
// tbl.style.backgroundColor = "blue"
var tbdy = document.createElement("tbody");
tbl.appendChild(tbdy);
for (var i = 0; i < 9; i++) {
var tr = document.createElement("tr");
tbdy.appendChild(tr);
for (var j = 0; j < 9; j++) {
var td = document.createElement("td");
td.appendChild(document.createTextNode("" + s[i][j]));
if (s[i][j] === 0) {
td.style.backgroundColor = "white";
td.style.color = "white";
}
tr.appendChild(td);
}
}
document.getElementById(position).appendChild(tbl);
document.getElementById("table1").style.padding = "0px";
}
// tests the possible 9 numbers for a field, if only one is possible then it's entered to the field
function test_possible_fields() {
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
if (sudoku[i][j] === 0) {
var numbers = 0;
var number = 0;
for (var k = 0; k < 9; k++) {
if (fields[i][j][k] !== 0) {
number = k + 1;
numbers++;
}
}
if (numbers === 1) {
sudoku[i][j] = number;
changesMade = true;
}
}
}
}
}
// tests the rows and cols
function test_rows_and_cols() {
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
if (sudoku[i][j] !== 0) {
var number = sudoku[i][j];
for (var k = 0; k < 9; k++) {
if (sudoku[i][k] === 0) {
if (fields[i][k][number - 1] !== 0) {
changesMade = true;
}
fields[i][k][number - 1] = 0;
}
}
var number = sudoku[i][j];
for (var k = 0; k < 9; k++) {
if (sudoku[k][j] === 0) {
if (fields[k][j][number - 1] !== 0) {
changesMade = true;
}
fields[k][j][number - 1] = 0;
}
}
}
}
}
}
// tests the blocks
function test_blocks() {
for (var k = 0; k < 3; k++) {
for (var l = 0; l < 3; l++) {
for (var i = 0 + k * 3; i < 3 + k * 3; i++) {
for (var j = 0 + l * 3; j < 3 + l * 3; j++) {
if (sudoku[i][j] !== 0) {
var number = sudoku[i][j];
for (var a = 0 + k * 3; a < 3 + k * 3; a++) {
for (var b = 0 + l * 3; b < 3 + l * 3; b++) {
if (sudoku[a][b] === 0) {
if (fields[a][b][number - 1] !== 0) {
changesMade = true;
}
fields[a][b][number - 1] = 0;
}
}
}
}
}
}
}
}
}
// tests if a sudoku is complete and returns eiter true or false
function sudoku_complete() {
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
if (sudoku[i][j] === 0) {
return false;
}
}
}
return true;
}
//Tests if there are any duplicate numbers in a sudoku
function sudoku_invalid(s) {
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
if (duplicateNumberExists(s, i, j)) {
return true;
}
}
}
return false;
}
这是html代码,不包含表格,因为它都是在javascript中生成的:
<div id="example-table" style="width: min-content">
<div id="table1"></div>
</div>
<div id="example-table2" style="width: min-content">
<div id="table2"></div>
</div>
<div id="example-table" style="width: min-content">
<div id="table3"></div>
</div>
<div id="example-table2" style="width: min-content">
<div id="table4"></div>
</div>
<br />
<button id="dl-png">Download as png</button>
在你的函数中window.onload = function ()
我在你打印第一个后添加了 resetSudoku()
。
看起来像这样:
function resetSudoku(){
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],
];
}
它重置数独。我怀疑错误在这里
function generateRandomSudoku(numbers) {
while (!sudoku_complete() || sudoku_invalid(sudoku)) {}
你检查数独是否未完成,但如果你不重置sudoku
,数独已经完成。
我正在构建一个具有随机性的数独生成器。在我的代码中,有一个生成该数独的函数。问题是我无法让两个数独不同
我尝试了 运行 两次该函数,但正如预期的那样,生成的两个数独完全相同。我希望当我复制整个函数并将其粘贴到下面时,数独会有所不同,但这样代码就会太多。
这是我的数独生成函数,为了让您更好地理解代码的作用,我添加了一些注释:
let 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],
];
let sudoku2 = JSON.parse(JSON.stringify(sudoku));
let changesMade = false;
let fields = [];
let counter = 0;
let sudoku3;
window.onload = function () {
generateRandomSudoku(25);
print_sudoku(sudoku3, "table1");
print_sudoku(sudoku, "table2");
// this is the code I used to generate the function twice
generateRandomSudoku(25);
print_sudoku(sudoku3, "table3");
print_sudoku(sudoku, "table4");
};
// solves a sudoku
function solveSudoku() {
fill_possible_fields();
changesMade = false;
counter = 0;
while (!sudoku_complete()) {
counter++;
test_rows_and_cols();
test_blocks();
test_possible_fields();
if (!changesMade) {
break;
} else {
changesMade = false;
}
if (counter === 100) {
break;
}
}
}
// returns true if there are two equal numbers in the same row
function duplicateNumberInRow(s, fieldY) {
numbers = new Array();
for (var i = 0; i < 9; i++) {
if (s[i][fieldY] !== 0) {
if (numbers.includes(s[i][fieldY])) {
return true;
} else {
numbers.push(s[i][fieldY]);
}
}
}
return false;
}
// returns true if there are two equal numbers in the same col
function duplicateNumberInCol(s, fieldX) {
numbers = new Array();
for (var i = 0; i < 9; i++) {
if (s[fieldX][i] !== 0) {
if (numbers.includes(s[fieldX][i])) {
return true;
} else {
numbers.push(s[fieldX][i]);
}
}
}
return false;
}
// returns true if there are two equal numbers in the same box
function duplicateNumberInBox(s, fieldX, fieldY) {
boxX = Math.floor(fieldX / 3);
boxY = Math.floor(fieldY / 3);
numbers = new Array();
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
x = i + 3 * boxX;
y = j + 3 * boxY;
if (s[x][y] !== 0) {
if (numbers.includes(s[x][y])) {
return true;
} else {
numbers.push(s[x][y]);
}
}
}
}
return false;
}
// returns true if there are two equal numbers in the same row, col or box
function duplicateNumberExists(s, fieldX, fieldY) {
if (duplicateNumberInRow(s, fieldY)) {
return true;
}
if (duplicateNumberInCol(s, fieldX)) {
return true;
}
if (duplicateNumberInBox(s, fieldX, fieldY)) {
return true;
}
return false;
}
// generates a random sudoku with a given amount of numbers in it
function generateRandomSudoku(numbers) {
while (!sudoku_complete() || sudoku_invalid(sudoku)) {
// new empty sudoku
sudoku3 = [
[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],
];
sudoku = JSON.parse(JSON.stringify(sudoku3));
// how many numbers are entered already?
let numbersDone = 0;
while (numbersDone < numbers) {
let fieldX = Math.floor(Math.random() * 9);
let fieldY = Math.floor(Math.random() * 9);
let number = Math.floor(Math.random() * 9) + 1;
//alert("" + fieldX + " " + fieldY + " " + number);
if (sudoku3[fieldX][fieldY] === 0) {
sudoku3[fieldX][fieldY] = number;
if (duplicateNumberExists(sudoku3, fieldX, fieldY)) {
sudoku3[fieldX][fieldY] = 0;
continue;
} else {
numbersDone++;
}
//alert("" + numbersDone);
}
}
sudoku = JSON.parse(JSON.stringify(sudoku3));
solveSudoku();
}
}
// fills the possible numbers for the fields
function fill_possible_fields() {
for (var i = 0; i < 9; i++) {
fields[i] = [];
}
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
fields[i][j] = [];
}
}
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
for (var k = 0; k < 9; k++) {
fields[i][j][k] = k + 1;
}
}
}
}
// show the sudoku as a table
function print_sudoku(s, position) {
var tbl = document.createElement("table");
// tbl.style.width = "500px"
// tbl.style.backgroundColor = "blue"
var tbdy = document.createElement("tbody");
tbl.appendChild(tbdy);
for (var i = 0; i < 9; i++) {
var tr = document.createElement("tr");
tbdy.appendChild(tr);
for (var j = 0; j < 9; j++) {
var td = document.createElement("td");
td.appendChild(document.createTextNode("" + s[i][j]));
if (s[i][j] === 0) {
td.style.backgroundColor = "white";
td.style.color = "white";
}
tr.appendChild(td);
}
}
document.getElementById(position).appendChild(tbl);
document.getElementById("table1").style.padding = "0px";
}
// tests the possible 9 numbers for a field, if only one is possible then it's entered to the field
function test_possible_fields() {
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
if (sudoku[i][j] === 0) {
var numbers = 0;
var number = 0;
for (var k = 0; k < 9; k++) {
if (fields[i][j][k] !== 0) {
number = k + 1;
numbers++;
}
}
if (numbers === 1) {
sudoku[i][j] = number;
changesMade = true;
}
}
}
}
}
// tests the rows and cols
function test_rows_and_cols() {
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
if (sudoku[i][j] !== 0) {
var number = sudoku[i][j];
for (var k = 0; k < 9; k++) {
if (sudoku[i][k] === 0) {
if (fields[i][k][number - 1] !== 0) {
changesMade = true;
}
fields[i][k][number - 1] = 0;
}
}
var number = sudoku[i][j];
for (var k = 0; k < 9; k++) {
if (sudoku[k][j] === 0) {
if (fields[k][j][number - 1] !== 0) {
changesMade = true;
}
fields[k][j][number - 1] = 0;
}
}
}
}
}
}
// tests the blocks
function test_blocks() {
for (var k = 0; k < 3; k++) {
for (var l = 0; l < 3; l++) {
for (var i = 0 + k * 3; i < 3 + k * 3; i++) {
for (var j = 0 + l * 3; j < 3 + l * 3; j++) {
if (sudoku[i][j] !== 0) {
var number = sudoku[i][j];
for (var a = 0 + k * 3; a < 3 + k * 3; a++) {
for (var b = 0 + l * 3; b < 3 + l * 3; b++) {
if (sudoku[a][b] === 0) {
if (fields[a][b][number - 1] !== 0) {
changesMade = true;
}
fields[a][b][number - 1] = 0;
}
}
}
}
}
}
}
}
}
// tests if a sudoku is complete and returns eiter true or false
function sudoku_complete() {
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
if (sudoku[i][j] === 0) {
return false;
}
}
}
return true;
}
//Tests if there are any duplicate numbers in a sudoku
function sudoku_invalid(s) {
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
if (duplicateNumberExists(s, i, j)) {
return true;
}
}
}
return false;
}
这是html代码,不包含表格,因为它都是在javascript中生成的:
<div id="example-table" style="width: min-content">
<div id="table1"></div>
</div>
<div id="example-table2" style="width: min-content">
<div id="table2"></div>
</div>
<div id="example-table" style="width: min-content">
<div id="table3"></div>
</div>
<div id="example-table2" style="width: min-content">
<div id="table4"></div>
</div>
<br />
<button id="dl-png">Download as png</button>
在你的函数中window.onload = function ()
我在你打印第一个后添加了 resetSudoku()
。
看起来像这样:
function resetSudoku(){
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],
];
}
它重置数独。我怀疑错误在这里
function generateRandomSudoku(numbers) {
while (!sudoku_complete() || sudoku_invalid(sudoku)) {}
你检查数独是否未完成,但如果你不重置sudoku
,数独已经完成。