Ten Pin Bowling Challenge I
I am sure that most of you are familiar with the game of bowling, mostly often played with ten pins. Today the local bowling alley needs our help and has tasked us with creating a function called bowling score. And you might have guessed it, but our bowling score function will need to return our bowler’s numerical score. To get this score we will be provided an array that represents the players ten frames. Each frame can be represented by three values, an ‘X’ for a strike, a number and a ‘/’ for spares, or lastly a numerical value should you not be able to pick up the previous.
Strap in as we first take a look at the background information we will need to get started and later look at my solution step by step. This code challenge can be found on Code Wars but I wont be giving away all the answers just yet.
Before we get started though we are going to cover some basics of the game, this way we know how the function should be built. For the first 9 frames each player gets a max of two chances to knock down all the pins down. Should they be able to do it in one roll, that current frame will end. On the 10th and final frame though players have a chance to get receive an extra role each time all the pins are knocked down, with a maximum of three. It is also worth note that strikes or spares do not offer any bonuses on the last frame. If you are familiar with how to keep score feel free the skip this next part, otherwise let’s get right into it.
Knowing how to decipher our scores per frame is also very important but don’t worry as it is not very complicated. Take for example we had a numerical score of 14 for our first frame. The first number represents the number of pins knocked down on our first roll and the second number, is the number of pins knocked down on our second roll. (1 + 4) = 5, simple conversion for numerical values but what about strikes and spares?
As stated above, our strikes will be represented with an ‘X’. This is when a player knocks down all the pins down on their first role. in the first nine frames, this will be an automatic ten points in addition to the to the points received in the preceding two roles. For example, let’s say we rolled a strike for our first frame and a 72 for our second, represented as such [ ‘X’, 72]. Our strike in this case will equal 19, because (10 + 7 + 2) = 19. Our second frame will be scored normally equating to 9.
Last but certainly not least we have spare, which again are represented as such ‘ 6/ ’ or just ‘ / ‘ depending on the format but be aware for both instances just in case. Scoring spares are exactly similar to that of a strike but with one difference. Instead of grabbing the score for the next two roles will only be grabbing one, the next roll after. Let’s take for example we were able to pick up the spare on our first roll but were only able to score 52 on our second, represented as [ ‘4/’, ‘52’ ]. Our score for the first frame will be 15 since (10 + 5) = 15. Our second frame will also be scored normally equating to 7.
Phew! There are some more terms as well as other ways for scoring multiple strikes such as a double, a turkey, and a four bagger as well as multiple spares in a row, but I plan to keep this function simple for now. Should the need arise and feel the need to make this function as complete as possible, I empower you to do so and further your research into the game! If you can wait for part II, we will make this fully functional, no pun intended.
Now that we are finally getting into the dirty of it, let’s get to the coding by grabbing a copy of the repo and start building out that function!
As we get started there are two things that I am going to do right from the start. The first is to create a variable of score set to zero, this will be our container for the total score. Secondly, our frames are presented to us as one long string with spaces between each score. Since I am already thinking that I am going to need to loop through each frame individually, I can split that string of frames from those spaces. By reassigning it to frames, we now have an array with each index being a single frame.
Now that our frames are in a more friendly format let’s start by creating a for loop so we can gain access to each of our values. We can then console log our array of frames based off our current index. Let’s take a look below.
Now that we have access to each value let’s start adding up those scores! As you are aware, we need to consider that we are not just dealing with numerical values so this is where we will need to create some conditional statements. The first and easiest in my opinion would be to say if our current frame is a number then we will make our score first equal to score, this ensures we keep carrying our current score over. Then we will need to parse integer each of the currents frames index’s and then add them together. While this may all sound a little crazy, taking a look at it really helps to understand what is going on.
Now that our numerical value conditional is out of the way lets start by creating our conditional for a strike. The first part of our conditions will check to see if X is included in the current frame and secondly, we need to make sure that the next frame is also a number. Then we will need to reassign score to score plus 10 plus the next two rolls, since this is a strike after all. You will see some similarities between this and our first conditional.
As you could have guessed, we are also going to need another conditional statement that will cover our payers should they get a spare. We will similarly check to make sure that our current frame includes a slash as well as the next frame being a number. Should that all check out we will again be reassigning score just as we did before but will only be grabbing the first roll from the next frame. Let’s take a look at the addition.
To me it seems like most of the basics are covered for our current tests except for a few and one of those is if someone should score a perfect game. We can do this any number of ways but because we are keeping our spare and strike functions very simple in comparison to what they could be. We will be changing our code around just a little bit.
We will create a conditional outside of our loop, should our frames be equal to a perfect game, 12 strikes, we will not even enter our loop in the first place since we don’t have too. We can do this by placing it in our else statement. I would also like to point out that using replace on the string of frames in this method will return a string with no spaces. Let’s take a quick peak at the changes we made.
Now that we have our conditions set up to handle a perfect game being thrown our way, we are still forgetting something though and it’s important. Do you know what it is? Well, all of these conditions that we just created within our for loop are only true when we are on the first 9 frames. We lose our bonuses on strikes and spares which in turn requires a different equation should they arise in the last frame. For this we simply create another if else statement within our loop.
Everything that we have completed up to this point in our loop, all our ternary conditionals, can be placed within our else statement. Our if statement will only execute should we be on our last index so we will make that it’s condition. From here we have a few of options but I am going to do pretty much what we did for frames but on a much smaller scale. The first thing we are going to do is split that last frame into single values since this can get a little complicated. Let’s take a quick peek at this setup below.
Now that we have our smaller secondary loop running its time to add those conditionals. I am going to follow a similar structure to that of my other ternary conditionals. I will first want to check if it is a number as well as if it is followed by another number. The reason for this is because a number followed by a slash, or both being a spare, the number will not matter as the value of a spare will override it. So, if it is a number followed by another number it will be added to our score total. Should our frame be equal to either an X or / , we will add 10 to our total score. Let’s look at the completed code.
This may seem like a very loaded function with many things going on and that wouldn’t be far from the truth. BUT we have completed our base version of our bowling score function. We are able to pass all the supplied test cases yet are still missing some parts. As stated earlier this mainly has to do with the fact we only set up our ternary conditional to work if a spare or strike followed by a number. In part II, we will add conditionals to handle such events as well as some restructuring as well. Remember, make it work first!
I would like to thank you for reading along and hope that you have learned something new! Take a look at part II! Keep an eye out for more articles the future as well!
If you would like to view a copy of these examples to play around with for yourself or just for reference, you can find the link for the GitHub Repo here.