You already know about variables, types, expressions... we could go on. The point is, you already know a few things about JavaScript. In fact, you know enough to write some real code. Some code that does something interesting, some code that someone would want to use. What you’re lacking is the real experience of writing code, and we’re going to remedy that right here and now. How? By jumping in head first and coding up a casual game, all written in JavaScript. Our goal is ambitious but we’re going to take it one step at a time. Come on, let’s get this started, and if you want to launch the next startup, we won’t stand in your way; the code is yours.
It’s you against the browser: the browser hides ships and your job is to seek them out and destroy them. Of course, unlike the real Battleship game, in this one you don’t place any ships of your own. Instead, your job is to sink the computer’s ships in the fewest number of guesses.
Goal: Sink the browser’s ships in the fewest number of guesses. You’re given a rating, based on how well you perform.
Setup: When the game program is launched, the computer places ships on a virtual grid. When that’s done, the game asks for your first guess.
How you play: The browser will prompt you to enter a guess and you’ll type in a grid location. In response to your guess, you’ll see a result of “Hit”, “Miss”, or “You sank my battleship!” When you sink all the ships, the game ends by displaying your rating.
For our first attempt we’re going to start simpler than the full-blown 7x7 graphical version with three ships. Instead we’re going to start with a nice 1-D grid with seven locations and one ship to find. It will be crude, but our focus is on designing the basic code for the game, not the look and feel (at least for now).
Don’t worry; by starting with a simplified version of the game, you get a big head start on building the full game later. This also gives us a nice chunk to bite off for your first real JavaScript program (not counting the Serious Business Application from Chapter 1, of course). So, we’ll build the simple version of the game in this chapter, and get to the deluxe version later in the book after you’ve learned a bit more about JavaScript.
We know we’ll need variables, and some numbers and strings, and if statements, and conditional tests, and loops... but where and how many? And how do we put it all together? To answer these questions, we need more information about what the game should do.
First, we need to figure out the general flow of the game. Here’s the basic idea:
Now we have a high-level idea of the kinds of things the program needs to do. Next we’ll figure out a few more details for the steps.
We have a pretty good idea about how this game is going to work from the high-level design and professional looking flowchart, but let’s nail down just a few more of the details before we begin writing the code.
For one thing, we can start by figuring out how to represent a ship in our grid. Keep in mind that the virtual grid is... well, virtual. In other words, it doesn’t exist anywhere in the program. As long as both the game and the user know that the battleship is hidden in three consecutive cells out of a possible seven (starting at zero), the row itself doesn’t have to be represented in code. You might be tempted to build something that holds all seven locations and then to try to place the ship in those locations. But, we don’t need to. We just need to know the cells where the ship is located, say, at cells 1, 2 and 3.
What about getting user input? We can do that with the prompt
function. Whenever we need to get a new location from the user, we’ll use prompt
to display a message and get the input, which is just a number between 0 and 6, from the user.
What about output? For now, we’ll continue to use alert
to show the output of the game. It’s a bit clunky, but it’ll work. (For the real game, later in the book, we’ll be updating the web page instead, but we’ve got a way to go before we get there.)
We need an approach to planning and writing our code. We’re going to start by writing pseudocode. Pseudocode is halfway between real JavaScript code and a plain English description of the program, and as you’ll see, it will help us think through how the program is going to work without fully having to develop the real code.
In this pseudocode for Simple Battleship, we’ve included a section that describes the variables we’ll need, and a section describing the logic of the program. The variables will tell us what we need to keep track of in our code, and the logic describes what the code has to faithfully implement to create the game.
You’re not going to get very far without some HTML to link to your code. Go ahead and type the markup below into a new file named “battleship.html”. After you’ve done that we’ll get back to writing code.
We’re going to use the pseudocode as a blueprint for our real JavaScript code. First, let’s tackle all the variables we need. Take another look at our pseudocode to check out the variables we need:
Let’s get these variables into a JavaScript file. Create a new file named “battleship.js” and type in your variable declarations like this:
We’ve got the variables out of the way, so let’s dig into the actual pseudocode that implements the game. We’ll break this into a few pieces. The first thing you’re going to want to do is implement the loop: it needs to keep looping while the ship isn’t sunk. From there we’ll take care of getting the guess from the user and validating it—you know, making sure it really is a number between 0 and 6— and then we’ll write the logic to check for a hit on a ship and to see if the ship is sunk. Last, we’ll create a little report for the user with the number of guesses it took to sink the ship.
Now we’re going to begin to translate the logic of our game into actual JavaScript code. There isn’t a perfect mapping from pseudocode to JavaScript, so you’ll see a few adjustments here and there. The pseudocode gives us a good idea of what the code needs to do, and now we have to write the JavaScript code that can do the how.
Let’s start with all the code we have so far and then we’ll zero in on just the parts we’re adding (to save a few trees here and there, or electrons if you’re reading the digital version of the book):
The browser provides a built-in function you can use to get input from the user, named prompt
. The prompt
function is a lot like the alert
function you’ve already used—prompt
causes a dialog to be displayed with a string that you provide, just like alert
—but it also provides the user with a place to type a response. That response, in the form of a string, is then returned as a result of calling the function. Now, if the user cancels the dialog or doesn’t enter anything, then null
is returned instead.
If you look at the pseudocode, to check the user’s guess we need to first make sure the user has entered a valid input. If so, then we also check to see if the guess was a hit or miss. We’ll also want to make sure we appropriately update the guesses
and hits
variables. Let’s get started by checking the validity of the user’s input, and if the input is valid, we’ll increment the guesses
variable. After that we’ll write the code to see if the user has a hit or miss.
Let’s look a little more closely at the validity test. You know we’re checking to see that the guess is between zero and six, but how exactly does this conditional test that? Let’s break it down:
This is where things get interesting—the user’s taken a guess at the ship’s location and we need to write the code to determine if that guess has hit the ship. More specifically, we need to see if the guess matches one of the locations of the ship. If it does, then we’ll increment the hits
variable.
Here’s a first stab at writing the code for the hit detection; let’s step through it:
Let’s put everything together from the previous couple of pages:
We’re almost there; we’ve almost got this game logic nailed down. Looking at the pseudocode again, what we need to do now is test to see if we have three hits. If we do, then we’ve sunk a battleship. And, if we’ve sunk a battleship then we need to set isSunk
to true and also tell the user they’ve destroyed a ship. Let’s sketch out the code again before adding it in:
After isSunk
is set to true, the while loop is going to stop looping. That’s right, this program we’ve come to know so well is going to stop executing the body of the while loop, and before you know it the game’s going to be over. But, we still owe the user some stats on how they did. Here’s some code that does that:
Now let’s add this and the sunk ship detection into the rest of the code:
Alright! We’ve now fully translated the pseudocode to actual JavaScript code. We even discovered something we left out of the pseudocode and we’ve got that accounted for too. Below you’ll find the code in its entirety. Make sure you have this typed in and saved in “battleship.js”:
let location1 = 3; let location2 = 4; let location3 = 5; let guess; let hits = 0; let guesses = 0; let isSunk = false;
while (isSunk == false) { guess = prompt("Ready, aim, fire! (enter a number from 0-6):"); if (guess < 0 || guess > 6) { alert("Please enter a valid cell number!"); } else { guesses = guesses + 1;
if (guess == location1 || guess == location2 || guess == location3) { alert("HIT!"); hits = hits + 1; if (hits == 3) { isSunk = true; alert("You sank my battleship!"); } } else { alert("MISS"); } } } let stats = "You took " + guesses + " guesses to sink the battleship, " + "which means your shooting accuracy was " + (3/guesses); alert(stats);
QA, or quality assurance, is the process of testing software to find defects. So we’re going to do a little QA on this code. When you’re ready, load “battleship.html” in your browser and start playing. Try some different things. Is it working perfectly? Or did you find some issues? If so list them here. You can see our test run on this page too.
Boolean operators allow you to write more complex statements of logic.
You’ve seen enough conditionals to know how to test, say, if the temperature is greater than 32 degrees. Or, that a variable that represents whether an item is inStock is true. But sometimes we need to test more. Sometimes we need to know not only if a value is greater than 32, but also if it’s less than 100. Or, if an item is inStock, and also onSale. Or that an item is on sale only on Tuesdays when the user is a VIP member. So, you see, these conditionals can get complex.
Let’s step through a few to get a better idea of how they work.
Say we need to test that an item is inStock AND onSale. We could do that like this:
We can simplify this code by combining these two conditionals together. Unlike in Simple Battleship, where we tested if guess < 0 OR guess > 6, here we want to know if inStock is true AND onSale is true. Let’s see how to do that...
We don’t have to stop there; we can use multiple boolean operators to combine conditionals in a variety of ways:
We don’t know how to bring this up, but you’ve been a little verbose in specifying your conditionals. What do we mean? Take this condition for instance:
As it turns out, that’s a bit of overkill. The whole point of a conditional is that it evaluates to either true or false, but our boolean variable inStock
already is one of those values. So, we don’t need to compare the variable to anything; it can just stand on its own. That is, we can just write this instead:
Now, while some might claim our original, verbose version was clearer in its intent, it’s more common to see the more succinct version in practice. And, you’ll find the less verbose version easier to read as well.
Yes, we still have one little matter to take care of because right now you’ve hard coded the location of the ship—no matter how many times you play the game, the ship is always at locations 3, 4 and 5. That actually works out well for testing, but we really need to randomly place the ship to make it a little more interesting to the user.
Let’s step back and think about the right way to place a ship on the 1-D grid of seven cells. We need a starting location that allows us to place three consecutive positions on the grid. That means we need a starting location from zero to four.
Now, once we have a starting location (between zero and four), we simply use it and the following two locations to hold the ship.
Take the random location along with the next two consecutive locations.
let location1 = randomLoc; let location2 = location1 + 1; let location3 = location2 + 1;
Okay, but how do we generate a random number? That’s where we turn to JavaScript and its built-in functions. More specifically, JavaScript comes with a bunch of built-in math-related functions, including a couple that can be used to generate random numbers. Now we’re going to get deeper into built-in functions, and functions in general, a little later in the book. For now, we’re just going to make use of these functions to get our job done.
We’re going to start with the Math.random
function. By calling this function we’ll get back a random decimal number:
What we need is an integer between 0 and 4—that is, 0, 1, 2, 3 or 4—not a decimal number, like 0.34. To start, we could multiply the number returned by Math.random
by 5 to get a little closer; here’s what we mean...
That’s closer! Now all we need to do is clip off the end of the number to give us an integer number. To do that we can use another built-in Math function, Math.floor:
That’s all we need. Let’s put this code together (we’ve already done that below) and replace your existing location code with it. When you’re finished, give it a few test runs to see how fast you can sink the enemy.
Here’s one of our test sessions. The game’s a little more interesting now that we’ve got random locations for the ship. But we still managed to get a pretty good score...
You’ve probably noticed that we made use of a few built-in functions like alert
, prompt
, console.log
and Math.random
. With very little effort, these functions have given you the ability to pop up dialog boxes, log output to the console and generate random numbers, almost like magic. But, these built-in functions are just packaged up code that’s already been written for you, and as you can see their power is that you can use and reuse them just by making a call to them when you need them.
Now there’s a lot to learn about functions, how to call them, what kinds of values you can pass them, and so on, and we’re going to start getting into all that in the next chapter where you learn to create your own functions.
But before you get there you’ve got the bullet points to review, a crossword puzzle to complete... oh, and a good night’s sleep to let everything sink in.
How does a crossword puzzle help you learn JavaScript? The mental twists and turns burn the JavaScript right into your brain!
ACROSS
1. This helps you think about how a program is going to work.
7. Both while and if statements use __________ tests.
8. Boolean operators always result in true or _________.
9. To get a true value from an AND operator (&&), both parts of the conditional must be ___________.
10. JavaScript has many built-in __________ like alert and prompt.
11. To randomly choose a position for a ship, use Math._________.
DOWN
1. To get input from a user, you can use the _________ function.
2. == is a _____________ operator you can use to test to see if two values are the same.
3. OR (||) and AND (&&) are ___________ operators.
4. If you’re good at testing programs, you might want to become a ________ Assurance specialist.
5. If you don’t initialize a variable, the value is __________.
6. We keep track of whether a ship is sunk or not with a ________ variable.
8. To get a false value from an OR operator (||), both parts of the conditional must be __________.
How does a crossword puzzle help you learn JavaScript? The mental twists and turns burn the JavaScript right into your brain! Here’s our solution.