user12793596
user12793596

Reputation:

get random item from javascript array repeatedly?

I'm making a Discord.js bot and one of the functions of the bot is to return a random item from a Javascript array of facts when a user types "!fact". This question has been asked a lot by other users and I've used code from answers given to them but I've run into one problem: the bot gets "stuck" on one fact and doesn't go through the list randomly every time "!fact" is typed. This is an example of the code I have so far:

var facts = [ "Fact 1", "Fact 2", "Fact 3", "Fact 4" ]
var fact = Math.floor(Math.random() * facts.length);

And then, for the bot to send the message:

client.on('message', message => {
    if (message.content === "!fact") {
        message.channel.send(facts[fact]);
        console.log('Message sent');
    }
});

But this would only return something like Fact 1 over and over, no matter how many times "!fact" is typed. How can I make it change every time?

Upvotes: 1

Views: 861

Answers (2)

Math.random() return a float value between 0 and 1, so multiply this number for an integer not necessary (almost never) return an integer number, that is actually what you need to iterate over an array.

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Math/random

The Math.random() function returns a floating-point, pseudo-random number in the range 0 to less than 1 (inclusive of 0, but not 1) with approximately uniform distribution over that range — which you can then scale to your desired range. The implementation selects the initial seed to the random number generation algorithm; it cannot be chosen or reset by the user.

To work around this you can typically use Math.round() or Math.floor.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor

The Math.floor() function returns the largest integer less than or equal to a given number.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round

The Math.round() function returns the value of a number rounded to the nearest integer.

Since you need to limit your range on your facts.length you can use Math.floor, to never get the length value since the index of arrays to start on 0, in other words, the index of the last fact is equal to (facts.length - 1).

client.on('message', message => {
  if (message.content === "!fact") {
    const factIndex = Math.floor(Math.random() * facts.length);
    const fact = facts[factIndex]
    message.channel.send(fact);
    console.log('Message sent');
}

});

Upvotes: 2

obscure
obscure

Reputation: 12891

You're determining your random fact just once at startup using this line:

var fact = Math.floor(Math.random() * facts.length);

To get a random fact each time the if-condition evaluates to true you need to re-assign a new random integer to facts in there:

    client.on('message', message => {
        if (message.content === "!fact") {
            fact = Math.floor(Math.random() * facts.length);
            message.channel.send(facts[fact]);
            console.log('Message sent');
        }

});

Upvotes: 4

Related Questions