Mini Battleship Console Game Tutorial

LaToya Simon
12 min readOct 13, 2023

10/13/2023

My name is LaToya and welcome to another session of Learning in Little bits!! With me! LaToya! You’re welcome! My main goal is to share with you some things I found fun and interesting on my journey to become a better dev and have I got a good chunk of change for you guys this time! I’ve been told this, and I see it coming to light, the best way to really see if you’ve got a handle on something you’ve learned is to teach it to someone else. These mini tutorials help me as much as I hope they are helping you guys. With that in mind, I will continue to do them.

Our last end of module project had us making a mini battleship console game that had four parts to it. Each part got increasingly more complex, sooooo I’m only going to be sharing part one of that experience or this little article might turn into some kind of thesis. That is definitely not learning in little bits. Have to stay in our lane.

Here are some of the terms and operators we will be using in this tutorial. If you are a beginner, it will be good to look at the documentation for a brief description before continuing. This tutorial is beginner friendly. We are however focusing on creating the Mini Battleship console game step by step, not a full-on explanation of each thing we used to make it. It is good to have some JavaScript knowledge already under your belt before we start. You will also want to brush up on these topics I’ve listed below.

Here is a list of resources before we go on:

· readlineSync npm:

o https://www.npmjs.com/package/readline-sync

· .toUpperCase():

o https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase

· .split():

o https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split

· .push():

o https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push

· Template literals:

o https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

· Random number generator:

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

· .flat():

o https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat

· Ternary:

o https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_operator

· .includes():

o https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes

· Bang(!) aka Logical Not Operator:

o https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT

Since you are at this point, I’m going to say that you at least glanced at the resources or are already familiar with the terms we will be using here. Good, let’s go ahead and jump right in.

Here is a list of the instructions I was given for the first part of this assignment from my class:

You are going to create your own small version of the classic board game Battleship. This is a terminal-based game.

If you don’t know how to play Battleship then watch this video.

This project will significantly increase your coding skills and help you master fundamental data structures and algorithms.

📣 Getting Started:

  1. Download the readline-sync npm package for this project.
  2. You WILL NOT need HTM/CSS to build this game. It is 💯 terminal-based, using only JavaScript.

🛠 Requirements: Part 1

  1. When the application loads, print the text, “Press any key to start the game.”
  2. When the user presses the key, your code will randomly place two different ships in two separate locations on the board. Each ship is only 1 unit long (In the real game ships are 2+ in length).
  3. The prompt will then say, “Enter a location to strike ie ‘A2’ “
  4. The user will then enter a location. If there is a ship at that location the prompt will read, “Hit. You have sunk a battleship. 1 ship remaining.”
  5. If there is not a ship at that location the prompt will read, “You have missed!”
  6. If you enter a location you have already guessed the prompt will read, “You have already picked this location. Miss!”
  7. When both of the battleships have been destroyed the prompt will read, “You have destroyed all battleships. Would you like to play again? Y/N”
  8. If “Y” is selected the game starts over. If “N” then the application ends itself.

Nice, this is the info we will be working with. Make sure to install the npm for readline sync in your terminal by entering: npm i readline-sync. You’ll see that in the documentation.

If you’ve read any of my previous articles, you’ll see that I like to break out the pseudo code right off the bat. It helps me to get my thoughts in order. Everyone does this step differently so don’t feel bad if yours looks differently than mine. Take a moment and try to make your own pseudo code before moving to the next step. Remember, you are just planning how you want to tackle each step.

**Pausing for dramatic effect!!!!***

Nice, if you are ready to continue, lets go right ahead.

  1. When the application loads, print the text, “Press any key to start the game.”
  • Log to console
  • Use readline sync keyInPause

2. When the user presses the key, your code will randomly place two different ships in two separate locations on the board. Each ship is only 1 unit long (In the real game ships are 2+ in length).

  • Need to use a random number generator
  • Need a board for the ships to be generated onto, an array or object
  • Need an array that keeps track of the ships locations on that board

3. The prompt will then say, “Enter a location to strike ie ‘A2’ “

  • Log to the console
  • Use readline sync question

4. The user will then enter a location. If there is a ship at that location the prompt will read, “Hit. You have sunk a battleship. 1 ship remaining.”

  • Need to be able to search through the board and compare the locations to the users guess
  • An array to keep track of the users input
  • Log to the console a hit when the users input matches whats in the ships array

5. If there is not a ship at that location the prompt will read, “You have missed!”

  • Log to the console when the users guess does not match whats in the ship array

6. If you enter a location you have already guessed the prompt will read, “You have already picked this location. Miss!”

  • If the users guess is already in the array, log to the console a miss

7. When both of the battleships have been destroyed the prompt will read, “You have destroyed all battleships. Would you like to play again? Y/N”

  • Need a way to track that both ships are hit, maybe take them out of the array
  • When the array.length is zero, log to the console a win
  • Ask if you user wants to play again, we can use readline sync

8. If “Y” is selected the game starts over. If “N” then the application ends itself.

  • If yes, call the game start again
  • If no, end the process

That looks easy enough to tackle right? Our skills so far are ready for this.

For number one, readline sync gives us the perfect method. The keyInPause utility method lets us ask the user a question and honestly just needs a sign from the user to let them know they are ready for the process to start. So press any key to start just said in a long way. It works when the user presses any key aside from enter.

On number two, we have a few things to call for. A random number generator will help us “randomly” select coordinates on our game board. It’s a really nice function that is easy to find if you are handy with google. We now need a game board. Let’s make an array that will accept a number for the size of the game board we want, and add the appropriate letters to correspond. Using the English alphabet, we have 26 letters, so we know that will be the most our board can go to. Since this is a mini battleship game though, we are only going to be making the 3 x 3 grid it asks for in the example. We want something that will make A1, A2, etc. A nice “for” loop should help us easily enough to attach a letter to a number and give us back an array right? You know how to play battleship by now, if not I suggest you take a moment to look at a youtube video. No shame in not knowing the game. You have resources. After watching a video or two, try tackling making a function that will load in your grid based off of the number you enter in as an argument. For example, buildGrid(3) will give a 3 x 3 grid from A1 to C3.

**Moment for you to pause***

Moment over!!! Are you ready to continue? Take your time.

Okay we are going now.

For the next part of number two, we needed something to keep track of the ships’ locations on the board, we can go ahead an just initialize an empty array to close off that step.

Let’s take a look at what we have so far:

To check off our list, we made a game board, we have a place to keep the ship coordinates that will randomly be generated, and we have a random number generator. Our next step is to make a function that will use the random number generator with our game board and give us two locations to add as ship coordinates. Some rules for placing the ship. They can not overlap. Actually one rule. Lol, much easier than you initially thought while reading that huh? So lets make a function that assigns two ship variables a random number. It needs to make sure the same number is not assigned to both ships. Then it needs to find that index on our game board and assign the coordinate to that variable. For example. Enemyship1 = B3.

Do you want to take a moment to give it a try before moving forward?

At this point, we are moving on, pause here if you aren’t ready to move on yet.

To explain what is happening in the screenshot below, we did exactly as we said we would. We set two variables to our random number generator function. If the numbers are the same, call the function to try again. Once they are different, push their coordinates from the game board array to our loadedBoard array. Now sometimes it isn’t easy to loop through so many arrays in arrays to look for a coordinate. In this case we know what we want to look for. The .flat() method collapses our game board into one big array so we can get what we need off the top layer. This is pretty handy. I suggest keeping this in your back pocket. We are setting a variable named max here equal to our flattened game boards length. This is for when we go to use our random number generator, it will be able to pick randomly up to as many spaces on the board.

In number three of our pseudo code, we want to prompt the user to input a coordinate as their first guess of where they think the ship could be. Readline sync question works great for this one because we can get the user’s input and set defaults to let them know what they can and can’t enter. We can use our flatGameBoard variable as the limit so they can only choose the coordinates generated for the current game. We can also leave a limit message to give them an idea of what that includes.

Here is what the function can look like. Again, feel free to try yourself first before continuing.

In number four, we want to be able to compare the user’s guess to the loadedBoard array to see if it is included. To help store the user’s input, initializing an empty guessArray will help us keep them safe. Then, If there is a hit, we want the console to log the hit message. For number five it wants us to add the missed message. We can put an if else statement to work here for these two.

Here is your time to shine! Try making the function before looking down below!

Ok, here is what I came up with.

It was pretty wonky. You probably noticed that the user input matched when using the readline sync limit to catch errors just fine, but didn’t really match when it came time to compare it to the loadedBoard array. To fix that, I set the userGuess to a new variable that was set to uppercase and it registered just fine. Also notice all throughout, I like to set console.log statements to show what’s happening. It’s a little easier to code when you can see what your code is doing.

For number six, it needs us to factor in if the user has already made the same guess or not. Good thing we have already been keeping track of the guesses. Let’s add a bang statement that will only continue if the usersGuess isn’t included in the guessArray. If it isn’t our function can continue as normal, and we can add pushing the guess to the guessArray here before we start looking for matches. Helps us DRY up our code a little bit. Remember, don’t repeat yourself! Try to clean up like that when you can. Then the else statement can be to add the log statement saying how the user already guessed that coordinate.

In number seven, we are needing to set up for the win condition.

To help us track if we hit all the battle ships, let’s have it remove a ship that has already been hit from the loadedBoard array. That way when the length of loadedBoard reaches zero we can inform the user of the win. After this, we can even upgrade our log statements to tell us how many ships are left using the template literals instead of just hard coding the numbers in.

Take a pause here and try it out first before continuing.

Okay, I’m excited to go, if you are still following along, don’t worry we are almost there!

Now that we have a way to remove things from loaded board, we can make a function that starts when it’s length reaches zero. For this function we can use the readline sync utility keyInYN. This will make it where the user needs to type y or n. Then we set what happens when either is hit. I’m going to say it again, reading through the readline docs are worth it. There are a lot of fun things you can do with this package. But, here we go. In this function, if yes is selected, we will have it call the game’s master start function. If no, it will end the process. Take note to call this function in the last function at the bottom so that it will only start when that condition is met. In the next part we will set the logic for starting the game. Don’t worry if you haven’t got that yet.

Number 8 is our last requirement. It needs us to start the game over if y is selected after the win, and cancel it if n is selected. You may also notice, that before this point, after guesses were made we hadn’t set it to let the user guess again. That is added to the to do list. The user needs to be able to guess again until the loadedBoard no longer has ships to attack.

We want our user to be able to make a guess and guess again until they have beat the game. So lets make a function that helps the user go back through the guessing process.

Then one master function that starts them all.

Do you have enough confidence to try and add those things now?

Take a pause here.

Since this is the last part, I’m going to go ahead and share the complete code cleaned up along with the logic I use to help it start when you first open it.

Well that does it for this tutorial. You should have a fully working mini battleship console game! Let me know what you thought of the process, I’m always striving to improve. Was this easy to follow? Not so much? I’d love to hear from you guys. Til next time everybody!

--

--

LaToya Simon

I am currently in the DevSlopes bootcamp, I was previously in the Thinkful bootcamp and decided I needed to continue my dev learning journey!