Dynamically creating multiple divs with random text elements from an array [SOLVED]

Dynamically creating multiple divs with random text elements from an array [SOLVED]
0

#1

I would like to feel my 6 divs

<div class="tile" id="tile0"></div>
<div class="tile" id="tile1"></div>

etc…

with numbers from an array = [1,2,3,1,2,3]
I want the numbers from the array to be added randomly.

I wrote a do/while loop hoping to iterate it as long as all elements will have inner html but it only fills one div and all others stay empty. Is there anything wrong with my while loop or I need a different approach?

let numberOfTiles = 6;
let randomNum = Math.floor(Math.random() * numberOfTiles); 

 let j = 0;
 do {
    document.getElementById(`tile${Math.round(randomNum/2)}`).innerHTML = array[j];
    j++
  
  }
  while (document.getElementsByClassName(`tile`).innerHTML);

#2

It’s only setting the random number once.


#3

Do you want the numbers to be added with replacement or without replacement? For example, without replacement would mean once one of 3’s has been chosen, there would still be the numbers [1, 2, 3, 1, 2] for the selection, then if the 2nd 3 was chosen, then there would only be [1, 2, 1, 2] left and so on.

If you want without replacement, then you could do something below. I took it a step further and made it generic enough so you could create the array of what ever size you want in the JavaScript and the html is created dynamically instead of having to hard code the html divs.

const array = [1, 2, 3, 1, 2, 3];
const createDiv = (tile, randNum) => `<div class="tile" id="tile${tile}">${randNum}</div>`;

let currTileNum = 0;
let bodyHTML = '';
do {
  let numberOfTiles = array.length;
  let randomIndex = Math.floor(Math.random() * numberOfTiles); // creates random index (0 thru array length - 1)
  let randomArrayNum = array.splice(randomIndex, 1); // removes one element from array based on random Index
  bodyHTML += createDiv(currTileNum, randomArrayNum);
} while (array.length); // stop after array is empty

document.body.innerHTML = bodyHTML;

#4

Thank you, but I wanted to do it the other way around. First numberOfTiles, so user can determine it and then array based on the number the user puts. It will be a memory game. The variable signsDouble will be the final array, with pairs of numbers (in this case 1-3)that will need to be shuffled.

let numberOfTiles =6
let signs=[];
function createArr() {
  for(i=1; i<=(numberOfTiles/2); i++){
    signs.push(i);
  }
  return signs
}
createArr();

let signsDouble = signs.concat(signs);

#5

Well, that is not very different than what you asked in your original post. Also, in your latest code, I see nothing where you are trying to randomize the order of the signsDouble array.

Anyway, you can still use most of my code, because My suggestion is you can use all of the code below my first line, because you have already have your array created. Just replace all references to the variable array in my code with signsDouble.


#6

I am still pretty lost. Here I create my divs and right after I try to fill them with while loop, but something is still wrong

for (let i=0; i<numberOfTiles; i++){
    let div = document.createElement('div');
    div.setAttribute('class', 'tile');
    div.setAttribute('id', `tile${i}`)
    container.appendChild(div);
    
    let j =0;
     do {
      let randomArrayNum = signsDouble.splice(randomNum, 1);
       document.getElementById(`tile${j}`).innerHTML = signsDouble[randomArrayNum]; 
       j++;
    }
     while (j<numberOfTiles);

#7

Not sure if you accidentally left off the closing } of your for loop, but if I put it at the end, I get a reference error in the following line, because randomNum is not declared in the code you posted. It would be much more productive, if you could post everything in a Codpen so we can both be on the same page instead of posting partial code back and forth.

  let randomArrayNum = signsDouble.splice(randomNum, 1);

#8

Of course.

Here is a link to the codepen.


#9

After reviewing your codepen, you have three glaring mistakes.

  1. You only assign a value one time to randomNum, so it will be the same index through the do while loop.

  2. Since numberOfTiles = 12, your random number formula can produce numbers like 6, 7, 8, 9 , 10, or 11, which would not be valid indexes of signsDouble which only has 6 elements.

  3. In your createStructure function you have a for loop which will loop 12 times and during each iteration of the for loop you have a do while loop which will iterate 12 times. Basically, this causes the signsDouble array to eventually become an empty array (after the first 12 slice calls on this array). Once it becomes an empty array, randomArrayNum will be [] so you end up assigning undefined to the inner html of each tile.


#10

I played around with your Codepen and I believe I simplified the code and organized it a little more. I created two versions. The first version uses the createElement method for each tile div and the second version creates the html as a string and then sets the container element’s inner html to that string

Version #1

function createStructure(numTiles) {
  //function that creates array of signs to be displayed on the tiles.
  function createSignsArr(numTiles) {
    const signs = [];
    for (let i = 1; i <= numTiles / 2; i++) {
      signs.push(i, i);
    }
    return signs;
  }

  const signsDouble = createSignsArr(numTiles);

  const container = document.createElement("div");
  container.setAttribute("class", "container");
  document.body.appendChild(container);
  for (let i = 0; i < numTiles; i++) {
    let div = document.createElement("div");
    div.setAttribute("class", "tile");
    div.setAttribute("id", `tile${i}`);
    let randomNum = Math.floor(Math.random() * signsDouble.length);
    let tile = signsDouble.splice(randomNum, 1)[0]; // [0] references 1st elem since splice creates one elem array
    div.innerHTML = tile;
    container.appendChild(div);
  } //end of for loop
} //end of createStructure function

window.onload = createStructure(12); // specify the number of tiles here

Version #2

function createStructure(numTiles) {
  //function that creates array of signs to be displayed on the tiles.
  function createSignsArr(numTiles) {
    const signs = [];
    for (let i = 1; i <= numTiles / 2; i++) {
      signs.push(i, i);
    }
    return signs;
  }

  const signsDouble = createSignsArr(numTiles);

  let container = document.createElement("div");
  container.setAttribute("class", "container");
  document.body.appendChild(container);
  let tilesHTML = "";
  for (let i = 0; i < numTiles; i++) {
    let randomNum = Math.floor(Math.random() * signsDouble.length);
    let tile = signsDouble.splice(randomNum, 1)[0]; // [0] references 1st elem since splice creates one elem array
    tilesHTML += `<div class="tile" id="tile${i}">${tile}</div>`;
  } //end of for loop
  container.innerHTML = tilesHTML;
} //end of createStructure function

window.onload = createStructure(12); // specify the number of tiles here

#11

@randelldawson thanks for taking time to give me feedback and play around with the code.
So it turns out I didn’t need a while loop at all. I had this feeling, but no clue how to approach it.

There are other nice features I need to add. I will share the link to the whole game, when I’m done with it.
Thank you very much!