1

I am new to Javascript and am making a memory game but i can't seem to get this code to work. What i am trying to do is choose a random element from my ids array and then remove it from that array but be able to use that value afterwards to assign it to an element in the cards array. What I came up with so far is this (updated):

const cards = document.querySelectorAll(".memory-card");

let ids = ["1", "1", "2", "2", "3", "3", "4", "4", "5", "5", "6", "6"];

function idHandler() {
    let rand = Math.floor(Math.random() * ids.length);
    let x = ids.splice(rand, 1)[0];
    cards[x].setAttribute("id", x);
}

cards.forEach(mapIds);

Since someone asked for the html elements:

<div class="memory-card" id="1">
    <img src="../assets/turned.png" class="front-face">
</div>
<div class="memory-card" id="1">
    <img src="../assets/turned.png" class="front-face">
</div>
<div class="memory-card" id="2">
    <img src="../assets/turned.png" class="front-face">
</div>
<div class="memory-card" id="2">
    <img src="../assets/turned.png" class="front-face">
</div>
<div class="memory-card" id="3">
    <img src="../assets/turned.png" class="front-face">
</div>
<div class="memory-card" id="3">
    <img src="../assets/turned.png" class="front-face">
</div>
<div class="memory-card" id="4">
    <img src="../assets/turned.png" class="front-face">
</div>
<div class="memory-card" id="4">
    <img src="../assets/turned.png" class="front-face">
</div>
<div class="memory-card" id="5">
    <img src="../assets/turned.png" class="front-face">
</div>
<div class="memory-card" id="5">
    <img src="../assets/turned.png" class="front-face">
</div>
<div class="memory-card" id="6">
     <img src="../assets/turned.png" class="front-face">
</div>
<div class="memory-card" id="6">
     <img src="../assets/turned.png" class="front-face">
</div>
5
  • 1
    I'm not really following what you're trying to accomplish, but have you looked at Splice for removing a random element from your array? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…? When you use splice(), the deleted element(s) are returned, so you can save them into a variable for use later. let removedItem = ids.splice(randomValue, 1); Commented Nov 10, 2020 at 20:19
  • 3
    Array.prototype.pop removes the last element from an array, it doesn't take any arguments. What you're looking for is Array.prototype.splice, which removes an element at a particular index. Commented Nov 10, 2020 at 20:20
  • 1
    x will not always be -1 with that code, although it will be quite a large proportion of the time. This is because you're trying to find the index in that array of a randomly-selected index from that array - the indices go from 0 to 11 and only "1" to "6" are present in the array. (I also have no idea why you are storing them as strings rather than numbers.) Commented Nov 10, 2020 at 20:20
  • @RobinZigmond, actually that is not what is happening with OP's code, the problem is not that the value of x is -1, the problem is that OP is using Array.prototype.pop( ) function. This function always removes the last function from the array. The OP did not know this so they assumed that the value of 'x' was always -1 and that is why the last element was being removed. Commented Nov 10, 2020 at 20:49
  • @Link - fair point, I only looked at how x was being calculated, and since that was clearly wrong, as well as what the OP was drawing attention to, I didn't see the need to look further before making my comment Commented Nov 10, 2020 at 20:50

3 Answers 3

2

You are trying to access the array incorrectly,

function idHandler() {
    let rand = Math.floor(Math.random() * ids.length);
    let x = ids[rand]
    ids.splice(rand,1) // can use this to remove an index from array
    cards[rand].setAttribute("id", x); // values should already be strings as they are stored with "" marks
}

You can actually skip a step if you don't need to use the variable x again

function idHandler() {
    let rand = Math.floor(Math.random() * ids.length);
    cards[rand].setAttribute("id", ids[rand]); // values should already be strings as they are stored with "" marks
    ids.splice(rand,1) // can use this to remove an index from array
}
Sign up to request clarification or add additional context in comments.

Comments

0

I will help you understand your existing code and where you are going wrong with it:

You don't need to get ids.indexOf(rand) here, the reason is because Math.Random is going to generate a number between 0 and 1 and then you are multiplying it with ids.length. Which means, the value of Math.random() will start from 0 and may go upto ids.length. Because your array is 0 based too, you can directly use this value and pass it as a parameter into the function you will use in order to split the array.

    let rand = Math.floor(Math.random() * ids.length); 
    let x = ids.indexOf(rand.toString()); 

Array.prototype.pop( ) function always removes the last element of the array and returns it's value. That is the reason why you are always getting the last element.

    ids.pop(ids[x]); 

What you can use instead is Array.prototype.splice(). What this function does, is it takes in 2 arguments - start index and end index, and it mutates the array, which means it will alter your original array. Also, it returns the value of the removed element in a new array.

I have added a snippet example of that below, you should run it and see the results, also it is a good idea to copy this code to your own IDE and try to debug it using console.log( ) to log values at every step and see what is happening to get a better understanding. Feel free to ask any queries in the comments below this question.

let ids = ["1", "1", "2", "2", "3", "3", "4", "4", "5", "5", "6", "6"];

function idHandler() {
    const rand = Math.floor(Math.random() * ids.length);
    const x = ids.splice(rand, 1)[0]; 
    //[0] in above line to return the removed element instead of an array 
    //containing the element
    console.log(x);
    console.log(ids);
}

idHandler();

8 Comments

This helped very much but now it can't identify cards[x] which is very weird imo. Maybe you know why this is but I will try to fix this myself for now. What i changed is this ` function mapIds() { let rand = Math.floor(Math.random() * ids.length) let x = ids.indexOf(rand.toString()) console.log(x) let removedId = ids.splice(rand, 1) ids.splice(x, 1) console.log(ids) cards[removedId[0]].setAttribute("id", removedId[0]) } `
can you try to do this and see what gets printed to the console - console.log(cards[x]);
cards variable as per the code you shared in the question is a Node List which has all the DOM Nodes which correspond to the class '.memory-card'. Can you update the question and show me all the elements in your HTML with the class '.memory-card' maybe I will be able to help with that info.
sometimes it outputs my html div and other times just undefined
I understand why nothing was working now. Thanks for the help and i will look into nodeLists myself tomorrow since it's alredy very late were I live
|
0

I think what you want is splice like so:

const cards = document.querySelectorAll(".memory-card");

let ids = ["1", "1", "2", "2", "3", "3", "4", "4", "5", "5", "6", "6"];

function idHandler() {
    let rand = Math.floor(Math.random() * ids.length);
    let x = ids.indexOf(rand.toString());
    var removedIds = ids.splice(ids[x], 1);
    cards[x].setAttribute("id", removedIds[0]);
}

cards.forEach(mapIds);

The function splice() removes elements from an array at the given position and returns the elements as array.

More info here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.