Lab 5: I'm Thinking of a Number

Mon Oct 26 16:25:43 EDT 2015

This lab is meant to help you learn the rudiments of the Javascript programming language and understand something of how web pages use Javascript, well enough that you can write a basic Javascript program that implements a simple game. You will also begin to develop some appreciation of why programming is not entirely trivial. It really does require orderly thinking and meticulous attention to detail.

Please read these instructions before beginning the lab.
Please follow the instructions about program format, variable names, etc.
Please use the template in Part 3.
Please pay attention to syntax and grammar and language constructs.

You can do this lab anywhere, but the lab assistants offer valuable advice not obtainable elsewhere.

Part 1: Introduction
Part 2: The Javascript Language
Part 3: Writing your own Javascript Program
Part 4: Finishing up

Part 1: Introduction

Programming languages provide a way to express computer algorithms in a form that is convenient for humans and can be translated into a computer's instruction repertoire. Programming languages are the way that we tell computers how to perform a task.

In class, we have studied the very low-level instructions that the computer itself understands (for example, the Toy), and talked about a variety of programming languages, much easier for people to use, that are translated into native machine instructions by programs like compilers and assemblers. There are many such languages, each with its own good and bad points, and often with noisy adherents and detractors.

Javascript, the topic of this lab and the next, is one of the most widely encountered languages, largely because it's available as part of every Web browser, and almost all web pages include Javascript code. You too can write Javascript programs that will be run by whoever views your web page. We don't expect you to become a full-fledged Javascript programmer, but you will do enough in this lab and the next to get some understanding of what programs look like and what is involved in taking an algorithm and turning it into a program that implements the algorithm.

You'll also be able to better understand the Javascript pages that you encounter when you browse, and in principle you'll be able to adapt and modify them for your own pages too.

There is an enormous amount of Javascript information on the Web, and thousands of books. You might start with this list of tutorials, or Google for "javascript tutorial". You might also take a look at Codecademy, which has a nice interactive walk through Javascript basics. Khan Academy also has lessons on Javascript.

Javascript has three major components:

In this lab, we're going to concentrate on programming, not on making the web page look fancy. This will mean using variables, arithmetic, loops and decisions, and functions, while doing only minimal interaction with the browser, just enough to get data from a user and to display results. The focus is on figuring out what the pieces are and how to combine them into logic that does a computational task.

Although a programming language provides a way for you to tell a computer what to do, you have to spell out the steps in sometimes excruciating detail (which is one thing that makes programming a challenge). To do this, you have at your disposal statements for:

Programming languages provide a number of piece-parts that you can use to help create a program quickly; in fact, you couldn't do much without some of these, and it would be very time-consuming to create others from scratch. In effect, these component are like prefabricated components for houses -- windows, doors, kitchen cupboards -- that can be used even by beginners to create polished products.

Some of the components are basic computational units: functions for mathematical operations (computing a square root or generating a random number, for example), or processing strings of characters (like finding or replacing a word within a sentence, or converting between upper and lower case).

Other building blocks let you manipulate things on a web page: forms, buttons, text display areas, and dialog boxes. When you run Javascript in a browser, sometimes your code makes the browser do things (pop up a dialog box, for example), while other times an external event causes the browser to run some of your code (a person pushes a button on a form). We saw a bit of this in an earlier lab, and there will be more in the next lab, but not much in this one.

Because Javascript runs within the confines of a browser and is meant to control some of what the browser does, it provides access to some browser facilities. It would be nice to say that this access was easy, clean, regular, and the same in all browsers, but that would be a lie. In fact, the interface is not hard, but it's far from clean and regular, and different browsers sometimes interpret identical Javascript statements differently, which is a source of frustration and irritation.

Use Firefox or Chrome instead of Internet Explorer and Safari, which are less helpful about identifying errors. Use the keyboard shortcut Command + Option + J (Mac) or Control + Shift + J (Windows/Linux) to bring up a window that helps identify syntax errors and other problems in your program. This advice will save you a lot of grief. Do not ignore it.

 


Part 2: The Javascript Language

Here we will provide a very brief overview of some of the commands and syntax available in Javascript. This is by no means a complete reference, however, so you will want to look at some of the web pages we suggested above, and review what was covered in class.

Since Javascript is mostly intended for behind the scenes operations in web pages, it's pretty clumsy for just displaying things, and the display in this lab is clumsy too. But it's enough to get started, and you can refine it later on.

Displaying messages with alert

Step 1 is to refresh your memory of what happened in the earlier lab. Create a new web page lab5.html that has this minimal information, and calls the library function alert to display a dialog box when the page is loaded:

	<html>
	<head>
	<title> My Javascript Guessing Game </title>
	<script>
	   alert("Got here");
	</script>
	</head>
	<body>
	   Test
	</body>
	</html>
This is the basic framework that you will now flesh out -- the single alert will gradually be replaced by more and more statements. You should create this file with whatever text editor you used for the earlier labs, using plain text. [Mac TextEdit users: be careful to save as plain text.] Be sure to save the results often, and reload the resulting web page after each change so you can be sure that your changes are working. Frequent small steps is the best strategy for both web page design and programming.

By the way, Firefox and Chrome both have a handy alternative to alert. If you use console.log(...) instead of alert(...), the results will be printed in the Console area instead of as a dialog box. Highly recommended.

Output with document.write

You can write any amount of any HTML with the statement document.write(...), and it will appear on the page that is being displayed as if it had been in the original file. This isn't entirely idiot-proof, but it's adequate for this lab. If you take the example above with alert and change it slightly:

	<html>
	<head>
	<title> My Javascript Guessing Game </title>
	<script>
	   document.write("<P> This comes from the script.");
	</script>
	</head>
	<body>
	   This comes from the body.
	</body>
	</html>
it will display
	This comes from the script.  This comes from the body.
That is, output from the script at the beginning comes before the body text because the script occurs before the body in the page source. If you put the script after the body text, however, the output order will also be reversed.

We'll use document.write to produce some of the output for this lab. You can also use it as an alternative to alert and the console log for debugging.

Internet Explorer and Safari, bless their hearts, do not always display output from document.write until after the page has been processed. Use Firefox or Chrome if you want to see output as your program runs.

Input and Output with prompt

The library function prompt is a sibling to alert; it pops up a dialog box with a message and a place for you to type a value; it's used in the Toy simulator. Whatever you type is returned as a sequence of characters that can be used in the rest of the program.

	<script>
	   var reply;
	   reply = prompt("Type your name");
	   alert("Hello " + reply);
	</script>

This sequence of statements declares a variable called reply. It then calls prompt and stores the resulting value (what the user typed) in the variable reply. Then it displays Hello and the reply text. The operator + joins two sequences of characters into one longer sequence of characters. You'll use it a lot in this lab.

The detailed behavior of prompt is a bit subtle. If you press OK or push Enter without typing anything, prompt returns an empty sequence of characters (that is, ""). If you hit the Cancel button, the returned value is null, which is a Javascript word for "nothing at all, not even no characters." Otherwise, what comes back is whatever the user typed in the box. This sequence will let you test for these conditions:

	answer = prompt("What's your name?");
	if (answer != "" && answer != null) {
	   // code for a non-empty answer goes here ...
	}

A third library function, confirm, pops up a dialog box with both OK and Cancel, then returns true if the OK button is pushed, and false if the Cancel button is pushed. This lets you write the if statements that will decide whether to play another game or quit, depending on the user's response; for example, it might be some variation on

	if (confirm("Another game?")) {
	   // code to play another game goes here ...
	} else {
	   // code to quit goes here ...
	}

This is enough to get through the rest of the basics; later on we'll show how to do somewhat better. From now on, we will only show the Javascript code but the <script> and other HTML tags have to be there.

Declaring Variables

A variable is a name that refers to a place in your program where information is stored; it ultimately corresponds to a location in memory. Variables can hold different types of information, but you don't generally have to worry much about that -- Javascript handles the details for you. The main types are integers (like 123), floating point numbers (with a decimal point and fractional part, like 3.14159), and text (a sequence of characters, like "hello, world").

Before you can use a variable in a Javascript program, you must declare it with the var statement; this tells the Javascript interpreter that you're going to be using a variable of this name so it can set aside a place in memory for it. For example:

var first_name, last_name;
var GPA;
Javascript distinguishes between upper case and lower case, so gpa and GPA are two different and unrelated variables.

A variable is a place to store a value so it can be used later in a program. To store a particular value in a variable, write variable = value. For example, to save the name from a user, you would write this:

    var name;
    name = prompt("What's your name?");
Then you can use the user's name later on in the program by using the variable name.

Quotes and quoting

If you need a literal string of characters in your program, like Hello, there, enclose it in either single ' quotes or double " quotes. If the string contains one kind of quote, you can quote it with the other. If you inadvertently omit a quote or don't balance quotes properly, it's an error and the most common symptom is that your program just doesn't work.
Make sure that your editor (e.g., Notepad, TextEdit) preserves the ASCII quote characters (the regular double-quote character on the keyboard); word processing programs think they are doing you a favor by using so-called "smart" quotes. If you see something about "illegal character" in the status bar or the Javascript console, check your quotes.

Arithmetic Operators, Expressions and Statements

Operators are special symbols like the + and - of ordinary arithmetic. An operator acts on values and variables to compute a new value; an expression is a legal combination of values and operators, like (my_height+your_height)/2 or area = pi * r * r.

These are the important operators:

Operator Description
=
Assigns the value on right to the variable on left (e.g., next_year = year + 1)
+ - * /
Arithmetic: add, subtract, multiply, divide
+
Strings: make a new string by joining the two operands
< <= > >=
Comparisons: less than, less than or equals, greater than, greater than or equals
== !=
More comparisons: equals, doesn't equal
&&
Conditional AND (true if left and right expressions are both true)
||
Conditional OR (true if either left or right expression is true)

A statement computes a value or does some other operation. For our purposes here, the main kinds of statements are simple function calls like alert("...") and assignments like x = 1. More complicated statements are described below.

Simple statements are terminated by a semicolon, as we have done in all the examples. Javascript allows you to omit the semicolon in many circumstances, but don't do that since it can cause or hide errors. Make sure each simple statement ends with a semicolon.

Control Flow Statements

Control flow statements like if-else, while, and for determine what the program will do next, depending on the evaluation of some expression. These are the Javascript versions of statements like goto and ifzero in the Toy computer, but easier to work with.

The If-else Statement

The if statement is used to select which one of two groups of statements to do next:
if (it's raining) { I will stay home } else { I will go outside }
or in code:
if (condition) {
   statements 
} else { 
   other_statements
}

If the condition is true, then the statements are performed, otherwise the other_statements are performed. Both groups of statements can be one or more lines. The braces surround the groups; you can omit them for a single statement, but it's safer to use them all the time.

The else part is optional; sometimes the logic doesn't require it and you can omit it. You can also string together a bunch of else if clauses to describe a sequence of decisions:

var temp;
temp = prompt("What's the temperature?");
if (temp > 212) {
   alert("boiling");
} else if (temp < 32) {
   alert("freezing");
} else {
   alert("in between");
}
Make sure you understand how this piece of code works. How would you modify it to work with Celsius temperatures?

Indentation and Spacing

Notice that we've indented the statements in the if-else code. Indentation emphasizes the structure and makes the code easier for humans to read and follow. It has no effect on how Javascript processes your program, but it makes a lot of difference in how easy it is to read. You must indent your code, following the patterns we use here. You're much less likely to make a mistake, we're more likely to be able to help you, and we're much more likely to be sympathetic if you do have problems.

Comments

Comments provide a way to add explanatory text to your code, making it more understandable to human readers. In Javascript, comments are indicated by // (a pair of slash characters). Everything on the line after the // will be ignored by the compiler.

var eecummings, EECummings;   // two different names

The While Loop

The while statement is a loop that causes a group of statements to be repeated while some condition is true:
while ( my room is a mess ) { pick up junk; throw it out }
In Javascript, this would look like
while (condition) {
   statements
}

As long as the condition is true, then the statements will be repeated. (That is, the condition is tested, and if it is true, then the entire loop body is executed, after which the condition is evaluated again.) As with if-else, the condition is surrounded by parentheses, the statements are surrounded by braces, and indentation is used to make it clear what is included in the loop.

So, for example, you might show a sequence of temperature conversions like this:

var celsius, fahr;
fahr = 0;
while (fahr <= 212) {
   celsius = 5 / 9 * (fahr - 32);
   document.write(fahr + "F is " + celsius + "C <br>");
   fahr = fahr + 10;
}
When you use while, watch out for infinite loops. Make sure that you increment or decrement the loop variable, or in some other way ensure that the loop ends eventually. (If you do create an infinite loop, you may have to kill the browser to recover.)

Functions

A function is a chunk of program that can be used or called from other places in a program to do an operation or compute a value; it's a way to wrap up a computation in a package so it can be easily used just by naming it. The Javascript library includes functions that have already been written for you -- mathematical functions like square root (which is called sqrt in Javascript) are good examples -- and you can write your own too.

For example, you could write a function to do the Fahrenheit to Celsius temperature conversion; putting the computation in a function makes it easier to change if necessary, and reduces clutter and confusion in the rest of the program. Here is such a function, called ftoc:

function ftoc(fahr) { // convert Fahrenheit to Celsius
   return 5 / 9 * (fahr - 32);
}
The return statement transfers control back to the function's caller, and sends a value back too if there is one. Notice that the statements of the function are enclosed in braces and indented.

Functions usually have parameters, so that they can operate on different data values, just like alert and prompt do. Thus ftoc has a single parameter, the temperature to be converted, which will be referred to as fahr within the function.

Now you could use ftoc in a loop like this:

function show_temps(low, high, step) {
   var f;
   f = low;
   while (f <= high) {
      document.write(f + "F is " + ftoc(f) + "C <br>");
      f = f + step;
   }
}
and then call the function in a statement like this:
show_temps(0, 212, 10);
Variables declared within a function are only accessible within that function; variables declared outside of any function are accessible anywhere in the program.

This program is available here so you can see how the components fit together,



Part 3: Writing your own Javascript Program

Your assignment is to implement a program that will play the old guessing game "I'm thinking of a number between 1 and 100". A no-frills version is only about 10 lines of code, and you should be able to do something nicer in fewer than 20 lines. If yours is getting much bigger than that, you're probably off on the wrong track and should review the notes and examples.

Please pay attention to syntax and grammar and language constructs. You can't just throw code fragments randomly into a file and expect them to work. Read the instructions. All the information you need is right here. Use the Javascript console to warn about syntax errors.

 

Your program should do the following:

  • When the page is loaded, a confirm dialog box asks if the user wants to play the game. OK means yes, Cancel means no.
  • When the game starts, it generates a new secret number, then prompts the user to enter a guess.
  • When the user enters a new guess in the "Guess my number" prompt, the program displays the appropriate message (like "50 is too high", "25 is too low", "37 is right"), using alert or prompt. The guess should also be displayed on the page with document.write.
  • If the answer was wrong, the user is prompted for another guess.
  • If the answer was right, that's the end of this game. The program tells the user it's right and displays the answer with document.write.
  • The user should then be asked about playing another game with confirm. OK means yes, Cancel means no.
  • It's a nicer user interface if you combine the appropriate too high/too low message with the prompt for the next guess, but it's not required.

    Program structure template

    You must put all of the logic for playing a single game in a function called play1game. The main part of your program then consists of a while loop that asks the user whether he or she wants to play a(nother) game, and if the answer is OK, calls play1game. Writing a separate function cleanly separates the logic for deciding whether to play again from the logic for playing one game, and you can test them separately. In particular, you can write a temporary version of play1game that just prints a message and returns, to be used while you're worrying about managing a sequence of games.

    Thus the structure of your program must be like this (inside <script> ... </script> tags):

            while (confirm("Want to guess my number?")) {
                play1game();
            }
    
            function play1game() {
                // statements to play one game go here
            }
    
    Download and use this template! Notice that this template works! Don't make gratuitous changes! You're just adding things to the body of play1game.

    When your program wants input, a dialog box will pop up and ask for input. This dialog box has a box you can check

    Prevent the page from creating additional dialogs.

    This is very helpful particularly when you get into an infinite loop (as will happen when you run this template). If you check this box, Javascript will no longer work correctly in your browser tab. This is easily fixed by closing the tab and opening a new tab.

    Playing one game

    Now you can work on playing a single game properly. The sequence of events is
    Generating a secret number

    You will need to declare a variable to hold the secret random number that the user is to guess. Call it secret. At the appropriate place in your program, you will need to compute a new secret number. Copy this line and paste it into the proper place in your Javascript code.

       secret = Math.floor(100*Math.random()) + 1;  // random number between 1 and 100
    
    The built-in function Math.random produces a different (pseudo-)random number between 0 and 1 each time it is called. Multiplying that value by 100 gives a number (including a fractional part) between 0 and 99.999... The built-in function Math.floor discards any fractional part, leaving an integer between 0 and 99. Adding 1 to that yields an integer between 1 and 100.

    Temporarily add an alert statement after this line to display the secret number, then test this part of the program. (It's much easier to test your program if you already know the right answer! Comment out this line of code once everything is working, but leave it in the code.)

    Fetching the Guess
    The next step is to fetch the guess that your user makes. This is the value that comes back from calling prompt. Store it in a variable called guess (which you must declare). Your code should handle Cancel and empty input properly; see the description of prompt above.
    Evaluating the guess

    Now you can go on to the real logic of the program: is the user's guess too high, too low, or just right? Your task is to do this test and decide what message to display and what to do subsequently. This will require a while loop that continues while the guess is not equal to the secret value, an if-else sequence inside the loop that compares the guess to the secret number, and another prompt() to fetch the next guess. Look back at the discussion of control flow and the examples in the class notes if you need to. Re-read this paragraph.

    One Step at a Time

    If this is your first Javascript program you are liable to make mistakes. Finding the bugs (debugging) will not be too hard if, as we suggested above, you write a small section at a time, and test as you go. This approach makes it much easier to determine what section of your code has the error: it's probably the one you just added.

    Use alert or console.log statements to display results as your computation proceeds, or to verify that your program is doing what you think it is. These are easy to add and help narrow down problems quickly.

    Inside your program, literal text values must appear inside quotes (e.g., "What's your guess?"). The + sign is used to join two text strings to form a new one (e.g., "Hi " + "There" is the same as "Hi There"). If you find that your program is printing text when you wanted numbers, use the parseInt function to converts a sequence of ASCII digits into their integer value.

    Comments

    Comments are annotations added by programmers but ignored by Javascript when it is compiling and running your program. Comments are used to make the code more readable for other people that may have to work on it, or to remind you of what you were thinking when you wrote a particular line of code. Javascript comments start with // and extend until the end of a line. We have included comments in some of the code above; you are advised to include comments of your own to remind yourself and others of what you are doing.

    When you prepare your lab for submission, you should leave any debugging statements in the program source code, but "commented out" so they can be easily restored if something goes wrong.

     


    Part 4: Finishing up

    Make sure that you have implemented what we asked for, listed above. When we grade, we will be looking to see that your program works, that it's reasonably cleanly written (properly indented, for instance), and whether you did anything special to make it more than the bare minimum. For instance, you could add a line or two to offer the user an upper limit different from 100, or a couple of lines to count the number of guesses.

    When everything is working, then

    Upload lab5.html to the CS dropbox for Lab 5 at https://dropbox.cs.princeton.edu/COS109_F2015/Lab5.
    Optional: If you wish, you can copy your lab5.html file to your cPanel site so others can play your amazing game.