0 Spicy Yoghurt | Last updated: 31 October 2026 | JavaScript tutorial
Generate random numbers in JavaScript
Generate random numbers in JavaScript with Math.random(). Get a random integer between two numbers, a random boolean or a random item from an array. Build your own random number generator, shuffle an array, give rare loot a small chance and get the same random numbers again with a seed.
Random numbers are behind a lot of things in a game. A dice roll, a critical hit, the spot where the next enemy shows up, the loot in a chest. In this tutorial you'll start with the basics of Math.random() and work your way up to all of those. Every example has code you can copy, and the demos let you see what's going on.
Generate a random number with Math.random()
In JavaScript, you generate random numbers with the Math object. It contains a lot of helpful mathematical functions, and one of them is random(). It gives you a floating-point number, a number with decimals, between 0 and 1. It can be 0, but it's always less than 1. You can use it anywhere in your code, without importing anything.
Here's an example of how to use Math.random() to generate a random decimal number:
Math.random();
// Possible output
0.8974465382241915
0.2958720891619725
0.006575835239084449
0.9456002830285726Every call gives you a new number. On its own, a number like 0.8974 isn't very useful yet. You'll need a little math to turn it into a dice roll, a position on the screen or a yes or no. That's what the rest of this tutorial is about.
Is it really random? Not quite. Math.random() is a pseudo-random number generator. The browser calculates every number with a formula, starting from a value it picks itself. The numbers look random and are spread evenly, and that's all a game needs. They're not unpredictable enough for passwords, though. More on that at the end of this tutorial.
Get a random number between two values
Imagine you need a random number somewhere between 0 and 10. Math.random() always stays below 1, so you need to make the range bigger. Multiply the result by 10, and you get a number between 0 and 10. For a range that starts somewhere else, like 5 to 10, multiply by the size of the range and add the minimum: Math.random() * 5 + 5.
The following function generates a random decimal number from a min value up to, but not including, a max value:
function getRandomNumber(min, max) {
return Math.random() * (max - min) + min;
}getRandomNumber(0, 10);
// Possible output
3.8690255118743275
0.15779814409071835
7.52113864188321
9.401215911876138You can use any range, even one with negative numbers or decimals. getRandomNumber(-1, 1) works, and so does getRandomNumber(0.5, 1.5). Just keep in mind that the output never reaches the max value.
Get a random integer between two numbers
Most of the time you need a whole number instead. A dice roll, a level, the number of enemies in a wave. A whole number that can be positive or negative is called an integer.
JavaScript doesn't have a separate type for integers. Every number is a Number, a floating-point value that also holds whole numbers exactly, up to Number.MAX_SAFE_INTEGER, which is 9,007,199,254,740,991. That's more than enough for dice. So to get an integer, you round the random number down with Math.floor():
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}This time, the result can include both the min and the max. That's what the + 1 is for. Let's roll a die:
// A dice roll from 1 to 6
getRandomInt(1, 6);
// Possible output
4
1
6
3How does it work? For a die from 1 to 6, max - min + 1 is 6. Math.random() * 6 gives a number from 0 up to, but not including, 6. Math.floor() cuts off the decimals, so you get 0, 1, 2, 3, 4 or 5. Add min, and you have 1 to 6, each with exactly the same chance.
A random number between 1 and 10 is getRandomInt(1, 10), and between 1 and 100 it's getRandomInt(1, 100).
What if the min or max isn't a whole number, like 1.5? In that case, first round the min up with Math.ceil(min) and the max down with Math.floor(max). Otherwise getRandomInt(1.5, 6) can give you 2.5, or even 6.5. MDN, Mozilla's documentation for web developers, rounds them the same way. In a game you'll usually pass whole numbers, so the short version above is all you need.
Why not use Math.round()?
There's a shortcut you'll see a lot, and at first glance it looks fine:
// Don't do this
function getRandomIntRounded(min, max) {
return Math.round(Math.random() * (max - min)) + min;
}It gives you numbers from 1 to 6 as well. But roll it a thousand times and count the results. Click Roll 1,000 times in the demo below, and switch between Math.floor() and Math.round().
With Math.floor(), all six bars stay close to the dashed line at 16.7%. With Math.round(), 1s and 6s come up only half as often as the other numbers: about 10% each, compared to 20% for 2, 3, 4 and 5. Why is that?
For a die from 1 to 6, max - min is 5. So Math.random() * 5 gives a number from 0 to 5. Math.round() turns everything from 0.5 to 1.5 into 1, which becomes a 2 on the die once you add min. But only 0 to 0.5 turns into 0, a 1 on the die. The numbers at the ends get half a slice, and the ones in the middle get a full slice. With Math.floor(), every number gets a slice of exactly the same size: 0 to 1, 1 to 2, and so on.
So stick to Math.floor() and the + 1. If a 6 only comes up once every ten rolls instead of once every six, your players will notice sooner or later.
You can test your own random functions the same way. Call them a thousand times, count how often each result comes up and check if the counts are about the same. Don't expect them to be exactly equal, though. With a thousand rolls, one number might come up 150 times and another 185 times. That's just chance.
Build a random number generator
Now you have everything you need for a random number generator. Pick a range, pick whole numbers or decimals and click Generate:
The demo uses the two functions from this tutorial: getRandomInt() for whole numbers and getRandomNumber() for decimals. Want a random number generator on your own page? Here's the complete code, in a single HTML file. Paste it into a file, open it in your browser and you're good to go:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Random Number Generator Tutorial | Spicy Yoghurt</title>
</head>
<body>
<h1>Random number generator</h1>
<p>
<label>Min <input id="min" type="number" value="1"></label>
<label>Max <input id="max" type="number" value="10"></label>
<label>
<input id="whole" type="checkbox" checked> Whole numbers
</label>
</p>
<button id="generate">Generate</button>
<p id="result"></p>
<script>
'use strict';
window.onload = init;
function init() {
let button = document.getElementById('generate');
button.addEventListener('click', generate);
}
function getRandomNumber(min, max) {
return Math.random() * (max - min) + min;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function generate() {
let min = Number(document.getElementById('min').value);
let max = Number(document.getElementById('max').value);
let whole = document.getElementById('whole').checked;
let result = document.getElementById('result');
if (whole) {
min = Math.ceil(min);
max = Math.floor(max);
}
if (max < min) {
result.textContent = 'Max is less than min';
return;
}
if (whole) {
result.textContent = getRandomInt(min, max);
} else {
result.textContent = getRandomNumber(min, max).toFixed(2);
}
}
</script>
</body>
</html>Number() turns the text from the input fields into numbers. For whole numbers, Math.ceil() rounds the min up and Math.floor() rounds the max down, so a min of 1.5 can't give you a 1. If the max is less than the min, the generator lets you know instead of giving a strange result. And toFixed(2) gives you the result as text, rounded to two decimal places.
You can download the random number generator here.
Generate a random boolean
A boolean is true or false, so a random boolean is like flipping a coin. You don't even need the functions above for this. Math.random() is below 0.5 exactly half of the time:
function getRandomBoolean() {
return Math.random() < 0.5;
}getRandomBoolean();
// Possible output
true
true
false
trueChange the 0.5 in getRandomBoolean(), and you can set any percentage chance you like. That's what you need for a lot of things in a game, like a 20% chance of a critical hit, or an enemy that drops a coin one out of every ten times. Say your game has a damage variable and a dropCoin() function:
// A 20% chance
if (Math.random() < 0.2) {
damage = damage * 2;
}
// A 1 in 10 chance
if (Math.random() < 0.1) {
dropCoin();
}Why < and not <=? Math.random() can be 0, but never 1. So Math.random() < 0.2 is true for exactly 20% of all the numbers it can give you. With <=, 0.2 itself would count too, and the chance would be a tiny bit more than 20%.
Pick a random item from an array
Need a random enemy, color or line of dialogue? Put them in an array and pick a random index. An array starts at index 0 and ends at length - 1, so you can use getRandomInt() from before:
function getRandomItem(array) {
return array[getRandomInt(0, array.length - 1)];
}let enemies = ['slime', 'bat', 'skeleton', 'ghost'];
getRandomItem(enemies);
// Possible output
'bat'Every item has the same chance. But the same item can come up twice in a row, and sometimes that feels wrong. Think of a tip on a loading screen, or the next song. Here's a simple fix: keep picking until you get something new.
let lastItem = null;
function getNewRandomItem(array) {
let item = getRandomItem(array);
while (item == lastItem && array.length > 1) {
item = getRandomItem(array);
}
lastItem = item;
return item;
}The array.length > 1 makes sure the loop stops when there's only one item to pick from.
Shuffle an array
What if every item should come up exactly once, in a random order? Think of a deck of cards, or a quiz with ten questions. Then you shuffle the array. You might find this one-liner online:
// Don't do this
cards.sort(() => Math.random() - 0.5);It looks clever, but the shuffle isn't fair. The function you pass to sort() tells it which of two items goes first, and Math.random() - 0.5 turns every answer into a coin flip. But sort() is built to put things in order, not to mix them up, so some orders come up a lot more often than others.
There are six ways to order three cards, so every order should have a 1 in 6 chance. Shuffle three cards this way in Chrome, and they end up in their original order more than a third of the time. Other browsers sort differently, but their results aren't fair either.
The right way is the Fisher-Yates shuffle. Walk through the array backward, from the last item to the second, and swap each item with a random item that comes before it, or with itself:
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
let j = getRandomInt(0, i);
let temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}let cards = ['ace', 'king', 'queen', 'jack', '10'];
shuffle(cards);
// Possible output
['queen', '10', 'ace', 'jack', 'king']Now every order has exactly the same chance. Note that shuffle() changes the array itself. Take the cards from the front with cards.shift(), one at a time, and you'll never draw the same card twice.
This is also the answer if you need random numbers without repeats. Put the numbers in an array, shuffle it and take them one by one.
Weighted random: make rare loot rare
In a lot of games, not every item is equally likely. A chest usually has a common sword in it, sometimes a rare shield, and once in a blue moon a legendary bow. Give every item a weight. The higher the weight, the bigger the chance.
let loot = [
{name: 'Common sword', weight: 70},
{name: 'Rare shield', weight: 25},
{name: 'Legendary bow', weight: 5}
];The weights add up to 100 here, so you can read them as percentages. They don't have to add up to 100, though. Here's how you pick an item:
function getWeightedItem(items) {
let totalWeight = 0;
for (let item of items) {
totalWeight += item.weight;
}
let roll = Math.random() * totalWeight;
for (let item of items) {
if (roll < item.weight) {
return item;
}
roll -= item.weight;
}
// Only reached through rounding errors with decimal weights
return items[items.length - 1];
}Imagine the weights as pieces of a line from 0 to 100. The sword takes 0 to 70, the shield 70 to 95 and the bow 95 to 100. The function throws a dart at a random spot on the line and walks along the pieces until it finds the one the dart hit.
Say the dart lands on 80. That's not below the sword's 70, so the function subtracts 70 and continues with 10. That's below the shield's 25, so you get the shield.
Let's open some chests:
Click Open 100 chests a few times. You'll find about 5 bows, but sometimes only 2, and sometimes 9 or more. That's chance for you. After thousands of chests, the share of bows gets very close to 5%.
You can use the same function for anything with odds, like which attack a boss picks, which enemy comes next or how many coins fall out of a broken pot.
Use random values in your game
A little randomness makes a game feel less scripted. Here are some ways to spice up your game, each with a line or two of code.
Make a coin appear at a random spot on the canvas. Here, x and y are the position of the coin's top-left corner. Subtract the size of the coin from the width and height of the canvas, so the coin never sticks out past the right or bottom edge:
let x = getRandomNumber(0, canvas.width - coinSize);
let y = getRandomNumber(0, canvas.height - coinSize);Not sure where (0, 0) is? It's explained in the tutorial on how to set up an HTML5 canvas game.
Send a particle off in a random direction. Pick a random speed in pixels per second and a random angle between 0 and 2 * Math.PI, a full circle in radians. Math.cos() turns them into the speed along the x-axis, and Math.sin() into the speed along the y-axis:
let angle = Math.random() * 2 * Math.PI;
let speed = getRandomNumber(50, 150);
let vx = Math.cos(angle) * speed;
let vy = Math.sin(angle) * speed;Give a bunch of particles a random direction, speed and lifetime, and you have an explosion. To move them smoothly, you multiply the speed by the time since the previous frame. That's explained in the tutorial about smooth canvas animation.
Spawn a new enemy every 1 to 3 seconds, instead of exactly every 2 seconds. spawnTimer holds the time until the next enemy appears. In your game loop, count it down. When it reaches zero, spawn an enemy and pick a new random time:
spawnTimer -= secondsPassed;
if (spawnTimer <= 0) {
spawnEnemy();
spawnTimer = getRandomNumber(1, 3);
}secondsPassed is the time since the previous frame, which you calculate in your JavaScript game loop. Set spawnTimer to a starting value, like 1 second, when your game begins. Without one, no enemy will ever show up. To make your game harder over time, shorten the wait a little after each new enemy, as shown in the tutorial about JavaScript game states.
Play the same sound with a slightly different pitch every time. A jump that always sounds exactly the same gets boring fast:
let jumpSound = new Audio('jump.mp3');
jumpSound.preservesPitch = false;
jumpSound.playbackRate = getRandomNumber(0.9, 1.1);
jumpSound.play();By default, the browser keeps the pitch the same when you change playbackRate. With preservesPitch turned off, a higher playbackRate also raises the pitch, just like a record that spins too fast.
For colors that always go well together, use hsl(). It describes a color by its hue, an angle on the color wheel from 0 to 360, and its saturation and lightness. Use the same saturation and lightness for every color, like 100% and 75%, and pick a random hue:
let color = 'hsl(' + Math.random() * 360 + ', 100%, 75%)';You can find out more in the colors section of the tutorial about drawing on the HTML5 canvas.
Let's put it all together in a small game. Pop the slimes, bats and ghosts before they disappear. Then switch to Fixed values and play the same game without any randomness:
With fixed values, every enemy is exactly like the one before it. It shows up in the same spot, moves at the same speed, explodes into a perfect ring and always drops a sword. After a few seconds, you know exactly what comes next.
In the random version, almost everything comes from the functions in this tutorial:
- Size, speed and lifetime - Every enemy gets its own, with getRandomNumber().
- Spawn time - A new enemy every 0.5 to 1.5 seconds instead of 1 to 3, with the spawn timer from above.
- Position - A ghost appears at a random spot on the canvas. A bat flies in from the left or the right, with getRandomBoolean().
- Enemy mix - Every group of six enemies has three slimes, two bats and a ghost, in a random order. That's shuffle().
- Explosion - 12 to 20 particles with getRandomInt(), each with a random direction, speed, size and lifetime, in a random hue.
- Critical hit - A 20% chance of a bigger explosion and double points.
- Loot - A popped enemy has a 1 in 3 chance to drop an item. getWeightedItem() picks a sword, shield or bow, with the same weights as in the treasure chest demo above.
- Pop words - A word like POP! or SPLAT! appears when you pop an enemy. getNewRandomItem() never picks the same word twice in a row.
A little randomness goes a long way, but too much makes a game feel unfair. A player should lose because of a bad move, not because of a bad roll.
Can you seed the random number generator?
In some programming languages, you can set the seed of the random number generator. The seed is the starting value for its formula, like the value the browser picks for Math.random(). Use the same seed, and you get exactly the same "random" numbers every time you run your script.
Why would you want that? Think of a level that's generated randomly but should be the same for every player. Or a daily puzzle, or the replay of a race. It also helps with a bug that only shows up with certain random numbers. With a seed, you can make it happen again and again, until it's fixed.
In JavaScript, you can't seed Math.random(). The browser picks its own seed and you can't change it. There's a proposal to add seeded random numbers to JavaScript, but no browser supports it yet. Luckily, a seeded generator only takes a few lines of code. Here's Mulberry32, a small and fast generator by Tommy Ettinger that's free to use:
function mulberry32(seed) {
let state = seed;
return function () {
state = (state + 0x6d2b79f5) | 0;
let t = Math.imul(state ^ (state >>> 15), state | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}Don't worry about the strange numbers and operators. Math.imul(), ^ and >>> mix up the bits of a 32-bit number, so the next number looks nothing like the previous one. You don't need to understand them to use the generator.
mulberry32() gives you a new function. Call that function, and you get a number between 0 and 1, just like with Math.random():
let random = mulberry32(1234);
random();
random();
random();
// Output, every time you run it
0.07329497812315822
0.7034119898453355
0.9028560190927237Use a whole number as the seed, like 1234, and create random once, at the top of your script. Then replace Math.random() with random() in all the functions that use it. After that, your dice rolls, shuffles and loot drops all depend on the seed.
In the demo below, a world is generated from random numbers. Click Draw again a few times with Math.random(), and then with mulberry32(seed):
With Math.random(), you get a new world every time. With the seed, the world stays exactly the same, until you pick a new seed. Found a nice one? Share your seed in the comments!
Want the player to get the same world back tomorrow? Save the seed with HTML5 local storage.
Random numbers for passwords and security
Math.random() is fine for games, but not for security. Its numbers are predictable: if someone sees enough of them, they can work out the next ones. So never use it for passwords, tokens, codes or anything that involves money.
For that, the browser has the Web Crypto API. crypto.getRandomValues() fills an array with random numbers that are safe to use. Here, it's a Uint8Array, an array that holds whole numbers from 0 to 255:
let bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
// bytes now holds 16 random numbers from 0 to 255Need a unique ID, for example for a saved game? crypto.randomUUID() gives you one in a single line:
crypto.randomUUID();
// Possible output
'3b241101-e2bb-4255-8caf-4136c566a962'Both functions work in all modern browsers. But crypto.randomUUID() only works on a page served over HTTPS or from localhost. A file you open straight from your own computer works too.
Common questions about random numbers in JavaScript
Is Math.random() really random?
No, it's pseudo-random. The browser calculates the numbers with a formula. They're spread evenly and look random, which is good enough for games and animations. For passwords and tokens, use crypto.getRandomValues().
Can Math.random() return 1?
No. It returns a number from 0 up to, but not including, 1. That's why getRandomInt() never goes past the max. Math.random() can return 0, but the chance is tiny.
How do I get a random number between 1 and 10?
Use getRandomInt(1, 10) from this tutorial. Without a function, it's Math.floor(Math.random() * 10) + 1. For a number between 1 and 100, use 100 instead of 10.
How do I get random numbers without repeats?
Put all the numbers in an array, shuffle it and take them one by one. See above for how to shuffle an array.
How do I make a random color?
Pick a random hue for hsl(), like 'hsl(' + Math.random() * 360 + ', 100%, 75%)'. There's more about colors in the tutorial about drawing on the HTML5 canvas.
How do I generate a random number in TypeScript?
The same way. Math.random() is part of JavaScript, so it works in TypeScript too. Just add the types: function getRandomInt(min: number, max: number): number.
Is Math.random() fast enough for a game?
Yes. A browser can call it millions of times per second. Drawing a single image on the canvas takes a lot longer than generating a random number.
Conclusion
Now you know how to generate random numbers in JavaScript. From a plain Math.random() to a dice roll, a shuffled deck, a weighted loot drop and a world that grows from a seed. Use Math.floor() and not Math.round(), and use crypto when it has to be secure.
Randomness is what makes a game different every time you play it. Want to put it to use? Start with the HTML5 game development tutorials and build your own game. If you have any questions or find a nice seed, feel free to share them in the comment section below.
Comments
Thanks! We've received your comment. We check every comment by hand before it appears, so this can take a few days.

No comments yet. Be the first to leave one!