01219245/javascript1/tutorial1

จาก Theory Wiki
(เปลี่ยนทางจาก 01219245/javascript1/practice1)
ไปยังการนำทาง ไปยังการค้นหา
This is part of 01219245

The best way to learn a language is to use it.

In this tutorial, we will write a simple number guessing game in JavaScript. Your goal is to guess a number between 1 - 100. If you guess incorrectly, a hint is given to you: if your guess is too high or too low. The game proceeds until you guess correctly.

An example of the interaction is given below:

Round 1, your guess?
40
Too low.
Round 2, your guess?
90
Too high.
Round 3, your guess?
75
Too high.
Round 4, your guess?
55
Great! That's correct.
  • YouTube Clips:
    • Part 1 - introduction, variables, control flows.
    • Part 2 - functions, I/O with alert() and prompt()
    • Part 3 - how to generate random numbers

Let's get started

Before we dive in to code the game, it's best to think about the overall picture. We code in small steps, but without the overall idea, it is very easy to get lost.

What are the steps, in the program, that we have to do?

  • Random the number
  • Read the guess
  • Check the guess and give hint
  • Repeat

First sketch

If we forget all the details, our JavaScript program would look like this:

var sol = randomSolution();
do {
    var guess = readGuess();
    if ( guess == sol ) {
        congratulate();
    } else if ( guess < sol ) {
        giveHint( 'Too Low' );
    } else {
        giveHint( 'Too High' );
    }
} while ( guess != sol );

This looks like a Java program! The control statements (if and do-while) should look familiar. There are things that look like methods randomSolution, readGuess, congratulate, and giveHint. We have two variables sol and guess. If you come from Java, you should see a major difference now.

A dynamic language

Notes: In this part, you will not write any code, but it is a discussion on the basic of dynamic language.

In Java, you declare a variable with its type. For example, you may say int sol;. However, in JavaScript, we do not specify variable's type; we only use keyword var to declare a local variable. It is not that data in JavaScript do not have types; they do. But the type information is in each piece of the data itself, not in the variable that keeps it.

In Java, you cannot do this:

  int a = 10;
  a = "dog";      // wrong type for variable a

But it is perfectly fine in JavaScript:

  var a = 10;
  a = "dog";     // ok.  (but this is not a good practice)

(However, it is not a good practice to do so.)

Since variables in JavaScript can carry any data types, their types depend on the data that they keep. This is a dynamic behavior, i.e. it is something that you have to figure out while the program runs. This is in contrast to Java where you know the type of a variable and every data that can be refer to by the variable during the compile time.

Languages where data type information can be figured out only at run time dynamically typed languages. JavaScript, Ruby, and Python are dynamic languages. On the other hand, languages like Java, C#, and C/C++, where variable types are fully specified at their declarations, are called statically typed languages. Since you are from Java, it might be confusing. After a while, you will get used to it.

Notes: You do not need the var keyword to use variables. But these variable will become global and will be hard to reason with. Therefore, it is a good practice to always use the var keyword. We will do some experiment on this issue too.

How to run a JavaScript program?

It should be very easy to run a JavaScript program on any computers. Most web browsers can interpret JavaScript. To make our life easier, we will use jsfiddle.net.

With jsfiddle, you can type in JavaScript program in the browser and run it. You will see 4 main panels: HTML, CSS, JavaScript, and Result. Let's try our program: put our JavaScript program above in the JavaScript box, and click Run.

You'll see nothing. Why? It is because our program uses many "commands" that we haven't defined. If you look at the browser's JavaScript console, you'll see a message like:

ReferenceError: randomSolution is not defined

Notes: How to look at JavaScript console? In Firefox, Menu -> Web Developer -> Web Console. In Google Chrome, Menu -> Tools -> JavaScript Console. In Safari, TBA. In IE, TBA.


Badge.png 1. Show the broken program and the error console to the TA.

Functions

In Java, you can define methods in a class. In JavaScript, you have more freedom to define a "function" that does not belongs to any classes or objects. The code below defines function randomSolution that only returns 55.

function randomSolution() {
    return 55;
}

Let's define all other functions that our program need. At this point, we want to run our broken program.

function randomSolution() {
    return 55;
}

function readGuess() {
    return 55;
}

function congratulate() {
}

function giveHint( message ) {
}

var sol = randomSolution();
do {
    var guess = readGuess();
    if ( guess == sol ) {
        congratulate();
    } else if ( guess < sol ) {
        giveHint( 'Too Low' );
    } else {
        giveHint( 'Too High' );
    }
} while ( guess != sol );

If you paste the above program into JSFiddle and click Run, you'll see nothing, but there won't be any error message in the JavaScript console.


Badge.png 2. Show the program that runs without any errors to the TA.

alert and prompt

To interact with the user, we can use "annoying" functions alert and prompt. These two functions are not part of the JavaScript language, but they are defined if you run your program in a browser.

We can modify congratulate to be

function congratulate() {
    alert( 'Great!  You guessed correctly.' );
}

If you run the program again, you should see the message.

The argument passed to alert is a String. You can use either single quotes (e.g., 'Hello') or double quotes (e.g., "Hello"). Try not to mix them in a single program.

We can also use alert to write function giveHint

function giveHint( message ) {
    alert( message );
}

However, when we run the program, we will not see any changes, since readGuess returns the correct guess, 55. If you want to try giveHint at this point you may want to change readGuess to return something other than 55. But then you'll run into an infinite loop; and you may have to type the whole program again.

Let's implement readGuess. This function must ask the user for a value. We can do that using function prompt. However, prompt return a string, while we want an integer. To do the conversion, we use function parseInt. The following is the function:

function readGuess() {
    var g = prompt();
    return parseInt( g );
}

You can click Run again, and you should be able to play with it for a bit now.


Badge.png 3. Show the program that can reads the user's guess to the TA.

Side Notes: type conversion

In fact, if you do not use parseInt in readGuess, the program still runs correctly. This is because in JavaScript, when you use == to compare two values, JavaScript tries to convert the values before performing the comparison, so

10 == '10'    # is true

We usually don't want this, because automatic conversion might cause subtle errors later on. To avoid this, we can use the === operator to compare. Like this:

10 === 10     # is true
10 === '10'   # is false

Note that there is also a !== operator as well.

10 != '10'    # is false
10 !== '10'   # is true

A note on coding style

You may notice a lot of spaces in the program listing above. This is to help readability. While computers execute your programs, but you should write them for people (including your future self).

In this course, we will take coding style seriously. We shall follow these Principles of Writing Consistent, Idiomatic JavaScript.

Let's take a look at some part of the document: Beautiful syntax.

if/else/for/while/try always have spaces, braces and span multiple lines
this encourages readability

Clearly, there are other references for JavaScript style guide, e.g., jQuery style guide, Crockford's code convention, and Google JavaScript Style Guide, so you can deviate slightly from the guideline. However, remember that you should be consistent.

Random numbers

Now, if you try to play nice, our game is somewhat usable. But you can always win by just guessing 55. 5555555

So let's add the crucial part of the game.

Wait a minute. Suppose I don't know how to do that, how can I figure out about this on my own? Yes, we should ask google! I tried to do that with the keywords:

javascript how to random number

and get this link: Math.random()

This function Math.random gives you a random number in the range from 0 to 1. (It will never give out 1.) This function gives you a floating-point number. So, you need to convert the result to an integer, we can do that by using Math.floor.

Our code for randomSolution becomes

function randomSolution() {
    return 1 + Math.floor(Math.random() * 100);
}

Let's play the game a few times to celebrate our first JavaScript program.


Badge.png 4. Show the game to the TA.

Showing round numbers

If you compare our program and the introduction carefully, we'll see that we still miss some feature. We do not have the round number counter.

Now, it's you task to add this functionality to the program.

Before you start hacking, let's pause for a moment and look at our main program to see where in the code this change should affect.

You can see that you may want to also change function readGuess so that it shows the round number. How can you do that? We can add an argument to the function like this:

function readGuess( roundNumber ) {
    var g = prompt( 'Round ' + roundNumber + ', your guess?' );
    return parseInt( g );
}

Then, add a counter to the main program and we should be done.


Badge.png 5. Show the complete game to the TA.

A better function

We have a working program. But there's something that we can do to make it even better, regarding the readGuess function.

One line in your main program should look like this

    var guess = readGuess( roundNumber );

It reads OK, but if you pay close attention to the code, you might wonder why readGuess should take roundNumber. What does it suppose to do with the roundNumber? The function name only implies that it read the user's guess, but the function name does not say anything about the round number.

We will perform a slight modification of the function. Instead of accepting the round number, it will accept the message to be shown.

function readGuess( message ) {
    var g = prompt( message );
    return parseInt( g );
}

Now if you look at the function name and its parameter, I think it is clearer and more descriptive.

We will move the expression 'Round ' + roundNumber + ', your guess?' to the main program now. The line calling function readGuess becomes:

    var guess = readGuess( 'Round ' + roundNumber + ', your guess?' );