Making a 6-sided die with JavaScript

I’ve picked up watching the ol’ Javascript tutorials again, after a period where I have been trying to take greater ownership of my role as a QA. One of the good things about having had this break, is that in the last couple of months since I have had to step up to the bar at work I have learnt a lot about learning.

That is to say, I’ve learnt a lot about the attitude you need in order to learn. I’ve always been really good at learning new things – one of those insufferable kids who listened intently in class, made a tonne of notes then never looked at them or revised, and then got good marks on the exams. That sort of thing works for history or geography, for sure. But when it comes to languages, you need to want to go out of your way to learn. I’ve had learning come so easy to me for so many years, that I didn’t know how to work at learning.

I had this realisation simultaneously with the one that in order to progress, you have to bite off more than your duties. You can’t just be really good at your job, then someone comes along and sees you’re good at thing A so they show you how to do thing B and thing C as well. You need to ask, and learn, and take on more than your responsibilites. Then people will retrospectively see that you’re the perfect person do do things B and C.

For learning, that means that I can’t wait around for someone to tell me what to build. Simply following along to some tutorials doesn’t make me good at Javascript. Having said that, there’s a difference between taking on more than you know, and biting off more than you can chew. I decided to make something small, so small I could do it in the Chrome inspector tab.

I was watching a video on some simple JS functions when I saw Math.random(). This function generates a random number between 0 and 1. I thought – how cool would it be to make a die! What follows is a breakdown of my process and mistakes, ending with an example of what I now know I should have done.

What’s the Math.random() function?

The Math.random() function generates a number between 0 and 1. You can take a look for yourself by opening the Web Dev tools of whatever browser you’re using and typing in “Math.random();”. Below is an example of some results:

Screen Shot 2018-10-19 at 15.39.15As you can see, it gives a different number every time it is run. That’s important to know for a bit later.

First off, I wanted to put that function inside a new function called dSix. When working with things you don’t know, I feel it’s best to start with the smallest possible amount of working code, then incrementally add to it and check it works at every stage. That way, if it’s broken you don’t have to check through every single thing you did. Just your most recent addition.

Screenshot 2018-10-25 at 09.23.07.png

Cool, that works. Time to actually make this do stuff. I will want to use the value spat out by Math.random() later on, but if I leave it as that then it would simply make me a new random number, instead of using the one I generated with the line above. Therefore, I created a variable to hold that number. It runs the random function once, then assigns that value to the variable and we access it from there. This way, we get a new number whenever we run dSix(), but not multiple times within that function.

Screenshot 2018-10-25 at 09.30.10

All still works!

For the next part, I needed to manipulate sixNum so that it would give a number between 1 and 6, instead of between 0 and 1.

You’re probably going to face-palm like Picard, because there is a very obvious solution – simply multiply by 6, and you have that! I’m an idiot, so I came up with a somewhat different solution…

Screen Shot 2018-10-19 at 13.55.03

I can only apologise to my ancestors and beg forgiveness for my silliness. What the above snippet does is multiply the random number by 10, meaning is is now a number between 0 and 10. I did this, and then I thought to myself – well hey now, this means my d6 could roll a 0 or number higher than 6. Can’t have that.

To prevent this, I created an if else statement saying “if ((the number is less than 1)) OR (the number is greater than 6)) {run the dSix() function again} else {tell me the number}”.

This means that I had a check inside my function to see if the result would be what I wanted. If it wasn’t what I wanted, it would re-run the function… from inside the funtion… until it got a number I like. Then it would log that number in the console. This is not an elegant solution, to say the least, but at the time I thought it was great so I carried on joyfully.

An obvious flaw in the above die is that it still gives a decimal number. dSix(); gave values like 1.3339836 or 4.080384. I just wanted nice whole numbers, so I googled the problem and found documentation about a few rounding functions. One rounded all numbers down, another rounded them all up, and the last did a split like I was taught in school (1.49999 = 1, 1.5 = 2). I chose this one, otherwise I would lose values for either 1 or 6.

I made a new variable called roundNum, and assigned it the value of Math.round(sixNum) to round that number. I changed the variable name in the if statement, but it wasn’t rounding anything. Being confused, I attempted to add a few debugging lines, as seen in the screenshot below. The function dSix() ran, it created a random number, it rounded that number to 2 and then logged the unrounded number.

Screen Shot 2018-10-19 at 14.39.10

I wanted to show this as an example of how I tried to work out my mistake, but also about how you should just double check your work. If you haven’t spotted it, the mistake was that I hadn’t changed the console.log line, therefore it was still logging sixNum instead of roundNum.

The final result

The final function looks like this:

Screen Shot 2018-10-19 at 15.40.56

And works like this:

Screen Shot 2018-10-19 at 15.46.29.png

I rolled it 100 times to see what the spread would be like, but I’m not a mathematician so I couldn’t explain why it looks like it does. Not a super even spread, but not too bad either.

Screenshot 2018-10-25 at 10.19.52

How could it have been better?

Looking back, it would have been relatively easy to make a die you could choose the number of sides with, ie instead of dSix(); you’d run dieRoll(6), with the option to use different die sizes. The way I chose to tackle this, by disregarding all numbers below 1 and above 6 needs to be changed, but we already know that wasn’t the best way to go about it.

The idea could be expanded further to include number of rolls, and even modifiers for Dungeons and Dragons. For example: dieRoll(2, 8, 4); could roll two d8, then add a +4 bonus to the damage, if written correctly. Additionally, you could create a function whose call could look like advantageRoll(20, true); to roll two d20, then take the highest number if you have advantage=true, or take the lowest number if advantage=false (if you have disadvantage on a roll). I might try again at a later date, as I think it’s really useful to have solid ideas of what you want to make before you start.

If you’d like to look at one that’s made with a lot more care, thought and knowledge then this is a good place to go. I would definitely use this as a starting block for creating the function above.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.