问题
I am trying to randomly fill a 2 dimensional array in JS but i want to have the numbers generated in each row and column to be unique.Here is my progression.This can do it for 3x3 grid I mean randomly generated numbers but I want the size of 9x9 like a real sudoku.Thanx.
//create table
function UpdateTable() {
var arr = [];
while(arr.length < 10){
var randomnumber = Math.floor(Math.random()*10);
if(arr.indexOf(randomnumber) > -1 ) continue;
arr[arr.length] = randomnumber;
}
tmp1 = 'cell' + 1;
tmp2 = 'cell' + 2;
tmp3 = 'cell' + 3;
tmp4 = 'cell' + 4;
tmp5 = 'cell' + 5;
tmp6 = 'cell' + 6;
tmp7 = 'cell' + 7;
tmp8 = 'cell' + 8;
tmp9 = 'cell' + 9;
var temp = [tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9];
for (var i = 0; i < 10; i++) {
document.getElementById(temp[i]).innerHTML = arr[i];
}
}
UpdateTable();
<center>
<div id="container">
<div id="header">
<h1>Welcome</h1>
</div>
<div id="content">
<table border="1" id="lotto">
<tr class="tr1">
<td class="normal" id="cell1"> </td>
<td class="normal" id="cell2"> </td>
<td class="normal" id="cell3"> </td>
</tr>
<tr class="tr2">
<td class="normal" id="cell4"> </td>
<td class="normal" id="cell5"> </td>
<td class="normal" id="cell6"> </td>
</tr>
<tr class="tr3">
<td class="normal" id="cell7"> </td>
<td class="normal" id="cell8"> </td>
<td class="normal" id="cell9"> </td>
</tr>
</table>
</div>
</div>
<input type="button" value="Re-generate Numbers" onclick="UpdateTable();" />
</center>
回答1:
Please check below code:
// we start with an empty sudoku...
var sudoku = new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
// ... and we solve it!!
solve(sudoku);
// given a sudoku cell, returns the row
function returnRow(cell) {
return Math.floor(cell / 9);
}
// given a sudoku cell, returns the column
function returnCol(cell) {
return cell % 9;
}
// given a sudoku cell, returns the 3x3 block
function returnBlock(cell) {
return Math.floor(returnRow(cell) / 3) * 3 + Math.floor(returnCol(cell) / 3);
}
// given a number, a row and a sudoku, returns true if the number can be placed in the row
function isPossibleRow(number,row,sudoku) {
for (var i=0; i<=8; i++) {
if (sudoku[row*9+i] == number) {
return false;
}
}
return true;
}
// given a number, a column and a sudoku, returns true if the number can be placed in the column
function isPossibleCol(number,col,sudoku) {
for (var i=0; i<=8; i++) {
if (sudoku[col+9*i] == number) {
return false;
}
}
return true;
}
// given a number, a 3x3 block and a sudoku, returns true if the number can be placed in the block
function isPossibleBlock(number,block,sudoku) {
for (var i=0; i<=8; i++) {
if (sudoku[Math.floor(block/3)*27+i%3+9*Math.floor(i/3)+3*(block%3)] == number) {
return false;
}
}
return true;
}
// given a cell, a number and a sudoku, returns true if the number can be placed in the cell
function isPossibleNumber(cell,number,sudoku) {
var row = returnRow(cell);
var col = returnCol(cell);
var block = returnBlock(cell);
return isPossibleRow(number,row,sudoku) && isPossibleCol(number,col,sudoku) && isPossibleBlock(number,block,sudoku);
}
// given a row and a sudoku, returns true if it's a legal row
function isCorrectRow(row,sudoku) {
var rightSequence = new Array(1,2,3,4,5,6,7,8,9);
var rowTemp= new Array();
for (var i=0; i<=8; i++) {
rowTemp[i] = sudoku[row*9+i];
}
rowTemp.sort();
return rowTemp.join() == rightSequence.join();
}
// given a column and a sudoku, returns true if it's a legal column
function isCorrectCol(col,sudoku) {
var rightSequence = new Array(1,2,3,4,5,6,7,8,9);
var colTemp= new Array();
for (var i=0; i<=8; i++) {
colTemp[i] = sudoku[col+i*9];
}
colTemp.sort();
return colTemp.join() == rightSequence.join();
}
// given a 3x3 block and a sudoku, returns true if it's a legal block
function isCorrectBlock(block,sudoku) {
var rightSequence = new Array(1,2,3,4,5,6,7,8,9);
var blockTemp= new Array();
for (var i=0; i<=8; i++) {
blockTemp[i] = sudoku[Math.floor(block/3)*27+i%3+9*Math.floor(i/3)+3*(block%3)];
}
blockTemp.sort();
return blockTemp.join() == rightSequence.join();
}
// given a sudoku, returns true if the sudoku is solved
function isSolvedSudoku(sudoku) {
for (var i=0; i<=8; i++) {
if (!isCorrectBlock(i,sudoku) || !isCorrectRow(i,sudoku) || !isCorrectCol(i,sudoku)) {
return false;
}
}
return true;
}
// given a cell and a sudoku, returns an array with all possible values we can write in the cell
function determinePossibleValues(cell,sudoku) {
var possible = new Array();
for (var i=1; i<=9; i++) {
if (isPossibleNumber(cell,i,sudoku)) {
possible.unshift(i);
}
}
return possible;
}
// given an array of possible values assignable to a cell, returns a random value picked from the array
function determineRandomPossibleValue(possible,cell) {
var randomPicked = Math.floor(Math.random() * possible[cell].length);
return possible[cell][randomPicked];
}
// given a sudoku, returns a two dimension array with all possible values
function scanSudokuForUnique(sudoku) {
var possible = new Array();
for (var i=0; i<=80; i++) {
if (sudoku[i] == 0) {
possible[i] = new Array();
possible[i] = determinePossibleValues(i,sudoku);
if (possible[i].length==0) {
return false;
}
}
}
return possible;
}
// given an array and a number, removes the number from the array
function removeAttempt(attemptArray,number) {
var newArray = new Array();
for (var i=0; i<attemptArray.length; i++) {
if (attemptArray[i] != number) {
newArray.unshift(attemptArray[i]);
}
}
return newArray;
}
// given a two dimension array of possible values, returns the index of a cell where there are the less possible numbers to choose from
function nextRandom(possible) {
var max = 9;
var minChoices = 0;
for (var i=0; i<=80; i++) {
if (possible[i]!=undefined) {
if ((possible[i].length<=max) && (possible[i].length>0)) {
max = possible[i].length;
minChoices = i;
}
}
}
return minChoices;
}
// given a sudoku, solves it
function solve(sudoku) {
var saved = new Array();
var savedSudoku = new Array();
var i=0;
var nextMove;
var whatToTry;
var attempt;
while (!isSolvedSudoku(sudoku)) {
i++;
nextMove = scanSudokuForUnique(sudoku);
if (nextMove == false) {
nextMove = saved.pop();
sudoku = savedSudoku.pop();
}
whatToTry = nextRandom(nextMove);
attempt = determineRandomPossibleValue(nextMove,whatToTry);
if (nextMove[whatToTry].length>1) {
nextMove[whatToTry] = removeAttempt(nextMove[whatToTry],attempt);
saved.push(nextMove.slice());
savedSudoku.push(sudoku.slice());
}
sudoku[whatToTry] = attempt;
}
showSudoku(sudoku,i);
}
function showSudoku(sudoku,i) {
var sudokuText = "<table border='1'>";
for (var i=0; i<=8; i++) {
sudokuText+="<tr>";
for (var j=0; j<=8; j++) {
sudokuText+="<td>";
sudokuText+=sudoku[i*9+j];
sudokuText+="</td>";
}
sudokuText+="</tr>";
}
sudokuText+="</table>";
document.write(sudokuText);
}
table {
display:table;
border: 2px solid #444;
border-collapse: collapse;
position: relative;
}
table tr {
display:table-row;
position: relative;
z-index:-1;
}
table td{
display:table-cell;
padding:8px;
border: 1px solid #ff0000;
text-align: center;
}
table td:nth-child(3), table td:nth-child(6){border-right: 5px solid #555; } /*vertical*/
table tr:nth-child(3) td, table tr:nth-child(6) td{border-bottom: 5px solid #555;} /*horizontal*/
I hope it might by helpful. Thanks
回答2:
I would consider a different approach.
Create a simple Sudoku board that looks like below basically shifting the first row by 3 positions to the right (every 3 rows ).
1,2,3,4,5,6,7,8,9 --> base row 1
4,5,6,7,8,9,1,2,3 --> shift base row 1 by 3 to right
7,8,9,1,2,3,4,5,6 --> shift base row 1 by 6 to right
2,3,4,5,6,7,8,9,1 --> shit base row by 1 to right (base row 2)
5,6,7,8,9,1,2,3,4 --> shift base row 2 by 3 to right
8,9,1,2,3,4,5,6,7 --> shift base row 2 by 6 to right
3,4,5,6,7,8,9,1,2 --> shift base row 1 by 2 to right (base row 3)
6,7,8,9,1,2,3,4,5 --> shift base row 3 by 3 to right
9,1,2,3,4,5,6,7,8 --> shift base row 3 by 6 to right
Call the above the basic Sudoku board.
You can now shuffle columns and rows and still have a legal formation of Sudoku board. You need to be careful though. Let's call rows 1-3 rowblock1, rows 4-6 rowblock2 and last 3 rows rowblock 3. Same thing for columns. We can swap row blocks with other row blocks and we can swap column blocks with other column blocks and still have Sudoku invariant set.
You can swap columns within same block.
You can swap rows within same block.
You can swap columns where the column index is a multiple of 3 columns away. (e.g column 1 and 4, columns 1 and 7, columns 3 and 9...etc)
回答3:
First create an array of 81 Position objects.
function Pos() {
}
const board = [];
for (let i = 0; i < 81; i++) {
board.push(new Pos())
}
Loop through the array (perhaps a few times) and create 3 arrays of arrays; vertical lines horizontal lines and the 9 sections
const xLines = [[], ...],
yLines = [[], ...],
sLines = [[], ...];
Each of these arrays should have 9 arrays of course. Populate them with references to the Position objects in the board variable.
Let each position in the board variable reference its horizontal/vertical line and section arrays.
//81 objects
//board = [{x, y, s, xArr, yArr, sectionArr}, ..]
now you'll be able to generate numbers, knowing which ones are already taken.
Pro tip: generate one horizontal line at a time (when you reach the 3rd, there is only 3 possible digits for each section)
回答4:
The way to do this is to
- create a variable representing an empty 9x9 array. use zeroes like [[0, 0, 0, 0, 0, 0, 0, 0, 0, ], ... etc.]
- write a function that will get all the numbers in the same row as a given coordinate, when you call e.g. same_row(x_coord, y_coord), returning a list
- write the same function to get all the numbers in the same column
- loop through your empty array, randomly choosing a number out of [1, 2, 3, 4, 5, 6, 7, 8, 9] that is neither in the same row, nor the same column, and filling the position with that number
A function that will return a list of the numbers in the same row as a square might look something like:
function (row_number, grid) {
var nums = []
for (var i = 0; i < 9; i++) {
nums.push(grid[row_number][i])
}
return nums;
}
Once you've coded it up yourself, submit this question again in code golf and use the answers to improve your own code :)
来源:https://stackoverflow.com/questions/51880325/sudoku-in-js-and-html