-1

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!

x00
  • 13,643
  • 3
  • 16
  • 40
Shawn
  • 132
  • 1
  • 1
  • 13
  • Can answer in grid style method. not display grid float left method that will be easy. – Abhinash Majhi Sep 11 '21 at 12:35
  • @AbhinashMajhi `float` would be a bad practice for coding. `float` is for floating images withing a text-block not for styling purpose. If you dont use grid, flexbox would be the right way to go. – tacoshy Sep 11 '21 at 13:02
  • Hello, the answer below answers your question does it not? Care to explain as to why you put a bounty on this question? – Alexandre Elshobokshy Sep 13 '21 at 14:05
  • @AlexandreElshobokshy The answer only helps me to solve the problem of creating grid. However, my code still shows error – Shawn Sep 13 '21 at 15:15

1 Answers1

4

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>
Abhinash Majhi
  • 499
  • 1
  • 4
  • 16
  • I works pretty well now! But do you know how how to solve the `Uncaught TypeError: Cannot set properties of undefined (setting 'textContent')` problem. I have been struggled with this for quite a long time – Shawn Sep 11 '21 at 15:38
  • The error means - you cannot set the property of undefined objects. Objects have keys and values. If you try to set the property of undefined you will get this error. In your case it is `textContent`. You should have in depth knowledge about how Objects work. Ref , I suggest you to learn about Objects. : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Undefined_prop – Abhinash Majhi Sep 11 '21 at 15:51
  • I have updated my question. I forgot to put all my code and I have updated my code. I understand the error meaning, but i don't know why this happens to my code. – Shawn Sep 11 '21 at 15:53
  • 1
    I exactly don't know what are you asking , if you want to get the width and height. you can use `.offsetHeight()`. Can you explain a little bit in succinct, I don't get you. – Abhinash Majhi Sep 11 '21 at 16:02
  • I edited and posted my code in my question (not only creating the grid , but also generate suitable number) but some reasons, my code keep showing `Uncaught TypeError: Cannot set properties of undefined (setting 'textContent')` when I wanna the number to be displayed in the grid I create. Do you why does this happen and how to solve this? Thank you very much! – Shawn Sep 11 '21 at 16:25