javascripthtmlcssmagic-square

Making different sizes of magic square


I'm making different sizes of magic square and want to get the values that the sum of each columns, rows and diagonal lines are the same in Javascript.

Here is my code:

var numsarray = [];
window.boxes = document.querySelectorAll(".box")
let time = document.getElementById('time')
let size = document.getElementById('select').value
var attempting = 0;
var output = {};
var arrays = [1,2,3,4,5,6,7,8,9];
var attempt = 0;
let boxparent = document.getElementById('boxParent')
let done = false;
var interval = setInterval(function() {
  attempting.textContent = attempt;
  time.textContent = parseFloat(time.textContent)+1
  if( time.textContent < 10 ) {
    return '00' + time.textContent;
  }
  if( time.textContent < 100 ) {
    return '0'+time.textContent
  }
},1)
// I could also use size**2
function createnums (){
  for( let i=1 ; i <= Math.pow(size,2) ; i++ ) {
    arrays.push(i);
  }
  return arrays;
}

let getnums = () => {
  arrays = createnums();
  numsarray = [];
  var len = arrays.length;
  while( len > 0 ) {
    attempt+=1
    var rans = Math.floor(Math.random() * len);
    numsarray.push(arrays[rans]);
    arrays.splice(rans, 1);
    len = len - 1;
  }
  return numsarray;
}

function creategrid(values) {
  // Get curent select value 
  boxparent.innerHTML = ''
  // Create grid from select value
  for( var i = 0 ; i < values.charAt(0) ; i++ ) {
    var rows = document.createElement('div');
    rows.className = 'row';
    for( var j = 0 ; j < values.charAt(0) ; j++ ) {
      var boxs = document.createElement('div');
      boxs.className = 'box';
      rows.appendChild(boxs);
    }
    boxparent.appendChild(rows);
  }
}

function size3x3(){
  while( ! done ) {
    output = getnums()
    if( output[0] + output[1] + output[2] == 15
     && output[1] + output[4] + output[7] == 15
     && output[2] + output[5] + output[8] == 15
     && output[0] + output[3] + output[6] == 15
     && output[2] + output[4] + output[6] == 15
     && output[3] + output[4] + output[5] == 15
     && output[6] + output[7] + output[8] == 15
     && output[0] + output[4] + output[8] == 15
    ) {
      window.clearInterval(interval)
      for( let i in output ) {
        boxes[i].textContent = output[i]
      }
      done = true;
    }
  }
}
function size4x4(){
  while( ! done ) {
    output = getnums();
    if( output[0] + output[1] + output[2] == 15
     && output[1] + output[4] + output[7] == 15
     && output[2] + output[5] + output[8] == 15
     && output[0] + output[3] + output[6] == 15
     && output[2] + output[4] + output[6] == 15
     && output[3] + output[4] + output[5] == 15
     && output[6] + output[7] + output[8] == 15
     && output[0] + output[4] + output[8] == 15
    ) {
      window.clearInterval(interval)
      for( let i in output ){
        boxes[i].textContent = output[i]
      }
      done = true;
    }
  }
}
   

.box {
   border: black 4px solid;
   background: white;
   opacity: 0.7;
   width: 175px;
   height: 150px;
   margin-top: 0px;
   cursor: pointer;
   float: left;
   display: inline-block;
}
.row {
   display: block;
   float: left;
   width: 100%;
}
<div id="boxParent"></div>
<form>
    <label>Choose a Size:</label>
    <select onchange='change()'>
        <option>3 X 3</option>
        <option>4 X 4</option>
        <option>5 X 5</option>
        <option>6 X 6</option>
        <option>7 X 7</option>
        <option>8 X 8</option>
        <option>9 X 9</option>
    </select>
</form>

I have been struggling with this for a long time.

Every time I reload the page, it shows Uncaught TypeError: Cannot set properties of undefined (setting 'textContent').

I am not really sure why. Do anyone know why does this happen?

Also, I would like to make an advanced algorithm that could check whether the sum of each columns, rows and diagonal lines are the same and I only need to make 1 function in all

Currently, I have to make every check function for every size of grid which is so annoying.

For the creategrid(), it only works for 3x3 and 4x4 size.

My code has several problem. Do anyone have a better version of doing this?

Thanks very much for any help and respond!


Solution

  • I hope this one is what you are looking. But I don't recommend to use float use latest flexbox or grid instead.

    window.boxes = document.querySelectorAll(".box")
    function creategrid(grid) {
      let values = grid;
      document.getElementById('boxParent').innerHTML=''
      for (var i = 0; i < values.charAt(0); i++) {
        var rows = document.createElement('div');
        rows.className = 'row';
        for (var j = 0; j < values.charAt(0); j++) {
          var box = document.createElement('div');
          box.className = 'box';
          rows.appendChild(box);
        }
        document.getElementById('boxParent').appendChild(rows);
      }
    }
    function change() {
      var x = document.getElementById("mySelect").value;
      creategrid(x)
    }
    .box {
          border: black 4px solid;
          background: white;
          opacity: 0.7;
          width: 50px;
          height: 50px;
          margin-top: 0px;
          cursor: pointer;
          float: left;
          display: inline-block;
        }
         .row {
              display: block;
              float: left;
              width: 100%;
            }
    <form>
              <label>Choose a Size:</label>
              <select id="mySelect" onchange='change()'>
                <option value='3 X 3' selected>3 X 3</option>
                <option value='4 X 4'>4 X 4</option>
                <option value='5 X 5'>5 X 5</option>
                <option value='6 X 6'>6 X 6</option>
                <option value='7 X 7'>7 X 7</option>
                <option value='8 X 8'>8 X 8</option>
                <option value='9 X 9'>9 X 9</option>
              </select>
            </form>
            
            <div id="boxParent"></div>