Search code examples
javascripthtmlvariablesdomrandom

Selecting a value and assigning as a variable is not working


For a Hangman game, I have some topics (eg:cities and animals).

When the user selects one of the topics, the outcome should be one of the chosen topic's random item. eg: London or Zebra etc.

Currently I only have random letter of selected topic.

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>


Solution

  • You seem to have issues getting a random value of a list depending on a selection.

    Currently, you are selecting a random letter of topicsEl.value instead of a random element of the associated topic's list.

    You need to determine the list to choose from depending on topicsEl.value. Dynamically this can be achieved if that value can be used as a key (e.g. for a dictionary), but this can also be done statically.

    But doing it statically would result in duplicate code, e.g. in an if-else-if ladder growing for each new topics list:

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

    Doing it dynamically allows for abstracting away the list selection, keeping the function simple. As suggested before, a dictionary can be used for this.

    For example, your dictionary's properties could each be a topic list, and your option values should then match their corresponding property's name:

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

    Selecting a random item of that list works analogous to how you are currently selecting a random letter:

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

    Personally, I find such random selections 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
    }