Home > Blockchain >  How to reset randomness in a function in a sudoku generator in javascript
How to reset randomness in a function in a sudoku generator in javascript

Time:04-04

I am building a sudoku generator which has randomness in it. In my code, there is a function that generates that sudoku. The problem is that I can't get the two sudoku's to be different

I tried running that function twice, but as expected the two generated sudoku's are exactly the same. I expect that when I copy the entire function and paste it underneath, the sudoku's will be different, but then there would be way too much code.

This is my sudoku generating function, I included some comments for you to better understand what the code does:

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;
  }

And this is the html code, which does not contain tables because it is all generated in 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>

CodePudding user response:

In your function window.onload = function () I added resetSudoku() after you print the first one.

that looks like this:

  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],
      ];
  }

It resets the sudoku. I suspect the error is here

function generateRandomSudoku(numbers) {
    while (!sudoku_complete() || sudoku_invalid(sudoku)) {}

you check if the sudoku is not completed but if you do not reset sudoku, the sudoku is already completed.

  • Related