search

Home  >  Q&A  >  body text

Title Rewrite: Troubleshooting Value Selection and Variable Assignment Issues

For the Hangman game, I have some themes (for example: cities and animals).

When the user selects one of the themes, the result should be one of the random items from the selected theme. For example: London or zebra crossing, etc.

Currently I only have random letters for the chosen theme.

const cities = ["New York", "London", "Berlin"]
const animals = ["Alligator", "Alpaca", "Zebra"]

const topicsEl = document.querySelector("#topics")

function randomTopic(){
return topicsEl.value[Math.floor(Math.random()*topicsEl.value.length)]
}

topicsEl.addEventListener("change", function(){
    console.log(randomTopic());
})
<div class="select">
   <label for="topics">Choose a topic:</label>

   <select id="topics">
   <option value=cities>Cities</option>
   <option value=animals>Animals</option>
   </select>
</div>

P粉596161915P粉596161915267 days ago496

reply all(2)I'll reply

  • P粉691461301

    P粉6914613012024-03-31 09:15:05

    In your existing code, topicsEl.value would be the string "cities" or the string "animals" (because these are the <select> value of an option.). These are not global variables that you define in JavaScript, they are just strings contained within the HTML.

    Then, in randomTopic(), access the string as an array and Javascript interprets it as an array of characters within the string that you want to treat it as. That's why you get a random letter from the word: "animals"[0] is the letter a, "animals"[1] is the letter n, and so on.

    What youtry do is select a random item from the array variables you named "city" and "animal", but your function doesn't try to touch those variables, they just act on String contained in the DOM.

    So you need to add a step to get from the string value in <select> to the array you are trying to access.

    You have defined both arrays as global variables; theoretically, these can be accessed as window.cities or window.animals, so you can do window [topicsEl.value] This will return the array you are trying to access....it's not very good practice to rely on window global variables though, so I encourage you to switch the pair of separate variables into one object so Visited:

    const topics = {
      cities: ["New York", "London", "Berlin"],
      animals: ["Alligator", "Alpaca", "Zebra"]
    }
    
    const topicsEl = document.querySelector("#topics")
    
    function randomTopic() {
      // find the desired array:
      let topicArr = topics[topicsEl.value]
      // return a random element from that array:
      return topicArr[Math.floor(Math.random() * topicArr.length)]
    }
    
    topicsEl.addEventListener("change", function() {
      console.log(randomTopic());
    })

    reply
    0
  • P粉696605833

    P粉6966058332024-03-31 00:41:15

    You seem to be having trouble getting a random value for a list based on a selection.

    Currently, you are selecting a random letter of topicsEl.value, rather than a random element of the associated topics list.

    You need to determine which list to select based on topicsEl.value. This can be achieved dynamically if the value can be used as a key (e.g. for a dictionary), but this can also be done statically.

    But static execution results in duplicate code, such as in a growing if-else-if ladder with each new topic list:

    function randomTopic() {
      if (topicsEl.value === "cities") {
        // ... (use citites)
      } else if (topicsEl.value === "animals") {
        // ... (use animals)
      } // Etc. for every new topic
    }
    

    Doing this dynamically abstracts away list selection, keeping functionality simple. As suggested before, you can use a dictionary for this purpose.

    For example, each attribute of the dictionary could be a list of topics, and then your option values ​​should match the names of their corresponding attributes:

    const topics = {
      cities: [/*...*/],
      animals: [/*...*/]
    };
    
    const topicsEl = document.querySelector("#topics");
    
    function randomTopic() {
      const list = topics[topicsEl.value];
      // ...
    }
    

    Selecting a random item in this list is similar to how you currently select random letters:

    function randomTopic() {
      const list = topics[topicsEl.value];
      return list[Math.floor(Math.random() * list.length)];
    }
    

    Personally, I find this random selection more readable if the index generation is in a separate function. Example:

    const edibles = ["cheese", "ham", "bread", "banana", "peanuts"];
    console.log(randomEdible());
    
    function randomEdible() {
      return edibles[randomInt(0, edibles.length - 1)];
    }
    
    function randomInt(max = 100, min = 0) {
      if (max < min) {
        [max, min] = [min, max]; // Swap
      }
      
      return Math.floor(Math.random() * (max - min + 1) + min); // +1 to include max
    }

    reply
    0
  • Cancelreply