DEV Community

Cover image for How to roll a dice in JavaScript?
Romain Guillemot
Romain Guillemot

Posted on • Originally published at rocambille.github.io on

How to roll a dice in JavaScript?

Let's build the ultimate dice step by step.

Last update: May 11, 2022

Math.random() as a basis

A dice is a tool providing a random integer each time you roll it. Something like that:

function rollDice() {
  return /* some randomly generated number */
}
Enter fullscreen mode Exit fullscreen mode

Every programming language has a built-in random function. In JavaScript, it's Math.random:

function rollDice() {
  return Math.random();
}
Enter fullscreen mode Exit fullscreen mode

That’s a good start: returning a random number. Remember Math.random is not “random enough” for serious things like cryptography, or casino games — read about Crypto.getRandomValues if that’s your business. Math.random is fair enough to roll a dice with friends. Let’s try it:

>> function rollDice() {
     return Math.random();
   }
>> rollDice();
<- 0.7367823644188911
Enter fullscreen mode Exit fullscreen mode

This 0.7367823644188911 is not really what we wanted… According to documentation, Math.random returns a decimal number between 0 (inclusive) and 1 (exclusive). For a 6-sided dice, we need an integer from 1 to 6. As a first guess, you may multiply by 6:

>> function rollDice() {
     return Math.random() * 6;
   }
>> rollDice();
<- 4.3380209914241235
Enter fullscreen mode Exit fullscreen mode

So we would have a random decimal number between 0 (inclusive) and 6 (exclusive). So far, so good. Next step would be to get integer values:

  • If 0 ≤ Math.random() * 6 < 1, return 1
  • If 1 ≤ Math.random() * 6 < 2, return 2
  • If 2 ≤ Math.random() * 6 < 3, return 3
  • If 3 ≤ Math.random() * 6 < 4, return 4
  • If 4 ≤ Math.random() * 6 < 5, return 5
  • If 5 ≤ Math.random() * 6 < 6, return 6

This can be done using Math.floor. Let's try again — with a for-loop to console.log multiple rolls:

>> function rollDice() {
     return Math.floor(Math.random() * 6);
   }
>> for(let i = 0; i < 5; i++) console.log(rollDice());
   5
   1
   4
   2
   0 // WTF?
Enter fullscreen mode Exit fullscreen mode

Once again, not exactly what we wanted... What we get here is:

  • If 0 ≤ Math.floor(Math.random() * 6) < 1, return 0. Not 1.
  • If 1 ≤ Math.floor(Math.random() * 6) < 2, return 1. Not 2.
  • If 2 ≤ Math.floor(Math.random() * 6) < 3, return 2. Not 3.
  • If 3 ≤ Math.floor(Math.random() * 6) < 4, return 3. Not 4.
  • If 4 ≤ Math.floor(Math.random() * 6) < 5, return 4. Not 5.
  • If 5 ≤ Math.floor(Math.random() * 6) < 6, return 5. Not 6.

To get the wanted result with Math.floor, we will have to add 1 before returning:

function rollDice() {
  return 1 + Math.floor(Math.random() * 6);
}
Enter fullscreen mode Exit fullscreen mode

Now we have a function to simulate our 6-sided dice :)

Yes, but… What if we want a 4-, 8-, 12- or 20-sided one?

No big deal: you can change the magic number 6 in the code for a parameter, passing the maximum value for your dice. Something like this:

function rollDice(max) {
  return 1 + Math.floor(Math.random() * max);
}

const rollDice4 = () => rollDice(4);
const rollDice6 = () => rollDice(6);
const rollDice8 = () => rollDice(8);
const rollDice12 = () => rollDice(12);
const rollDice20 = () => rollDice(20);
Enter fullscreen mode Exit fullscreen mode

The ultimate dice

I was once inspired by a vision: “The Ultimate Display” by Ivan E. Sutherland, 1965. Among others, I like this quote:

There is no reason why the objects displayed by a computer have to follow the ordinary rules of physical reality with which we are familiar.

We used a parameter to replace the number of sides of our dice. Why not removing the other magic number? This ugly 1 may become an other parameter:

function rollDice(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

const rollDice4 = () => rollDice(1, 4);
const rollDice6 = () => rollDice(1, 6);
const rollDice8 = () => rollDice(1, 8);
const rollDice12 = () => rollDice(1, 12);
const rollDice20 = () => rollDice(1, 20);
const rollSomeUltimateDice = () => rollDice(42, 42);
Enter fullscreen mode Exit fullscreen mode

This final version allows to simulate a dice which is not starting at 1. Moreover the max allows to simulate a uniform fair dice beyond “the ordinary rules of physical reality”. Imagine a 7-sided one. You can mimic your favorite dice game following its ordinary rules. But if you can imagine one, roll a dice which would never exist in reality ;)

Latest comments (1)

Collapse
 
koreander profile image
Koreander • Edited

Hi great but..
always a dice can be rol 1 to MAX sides them
min = 1 always soo

function rollDice(sides) {
return (1-1) + Math.ceil(Math.random() * (sides-1+ 1))
}

Converting the expresion more simple

function rollDice(sides) {
return Math.ceil(Math.random() * sides)
}

rollDice(6)
rollDice(10)
rollDice(12)
rollDice(20)
rollDice(100)

if you want several dices !!
several call to the function.. good day!!

But the floor function its the base so depends what you want to be. simple easy or mor exactly case