Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need to build a new array by randomly picking 18 numbers from another array and also having those same numbers be in the new array twice

I am making a matching game for a group project in a JavaScript Jquery class. I have 36 images that I can use for the tiles. I want the game to randomly pick 18 of these and put them into a new array. I also need these 18 numbers in the new array twice, because that new array is going to be shuffled and then used the build the game board.

Here is my code:

let objects = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29','30', '31', '32', '33', '34', '35', '36'],

function cardList () {
    var cardList = [36];
    for (i = 0; i < cardList.length; i+=2) {
        cardList[i] = objects[Math.floor(Math.round((Math.random()*36)+1))];
        cardList[i+1] = cardList[i];
    }
    return cardList;
}

I tried to use the Chrome debugger on this and it this isn't creating all the numbers, it's just creating the two initial numbers.

There has got to be a better way to do this, I have looked at several examples of a matching game and most of those have the exact number of cards needs, which may be causing me problems.

like image 407
Lisa Avatar asked Mar 07 '23 01:03

Lisa


2 Answers

Since you (probably) don't want items to appear more than twice in the result, you should choose items without replacement. This is how I would do it:

const objects = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29','30', '31', '32', '33', '34', '35', '36'];
const getList = () => {
  const objs = objects.slice(0);
  const selected = [];
  for (let i = 0; i < 18; i++) {
    const index = Math.floor(Math.random() * objs.length);
    const [num] = objs.splice(index, 1);
    selected.push(num, num);
  }
  return selected;
};
console.log(getList());
like image 111
CertainPerformance Avatar answered Mar 16 '23 08:03

CertainPerformance


To pick the numbers I would simply shuffle the array and take 18 unique elements from it. The best method to shuffle an array is the Fisher-Yates shuffle, below implementation for the shuffle is taken from this answer. All you need to do then is to "concat the array with itself" and you got your starting array with 18 numbers that all exist twice in the array. You could obviously directly shuffle the resulting array then, and voila.

let array = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29','30', '31', '32', '33', '34', '35', '36'];

function buildCardList(array) {
  const shuffled = shuffle(array).slice(0,18);
  return shuffle(shuffled.concat(shuffled));
}


console.log(buildCardList(array));


// Origin: https://stackoverflow.com/a/2450976/3993662
function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}
like image 26
baao Avatar answered Mar 16 '23 07:03

baao