JavaScript Tutorial: Alternative coin toss

This tutorial describes how to prepare a coin toss program using HTML5, namely drawing the coin faces on canvas and using clicking on the canvas as the event that triggers the action. It would be beneficial to have read my tutorial for a coin toss using a form and an img tag. This repeats much of the material and it is important to appreciate what is the same and what is different.

The starting screen for the HTML5 coin toss is

When the player clicks in the outlined rectangle, a coin face appears:

In this case, this is the tail (reverse) of the Native American $1 coin series. When I clicked again on a different place, this screen appeared:

It is important to recognize that the action is based on pseudo-random processing, so you may not get tail / head /tail / head, etc.

Repeating the format of the other tutorial, here are the critical tasks to be done.

Key Design Issues

Task: Generate a value randomly between zero and one.

Logic: JavaScript, in common with most other programming systems, has facilities for generating what are termed pseudo-random numbers. The qualifier 'pseudo' is used because the computer system performs a well-defined procedure but the results appear to be random.

Solution: We will use the JavaScript function Math.random that generates a fraction from zero to (just under) one.

Task: Make a decision, choosing to execute one set of statements versus another based on a value.

Logic: JavaScript, in common with most other programming systems, has conditional statements.

Solution: Use JavaScript's if statement. An expression, called the condition, is evaluated. If it is true, then one set of statements is executed; otherwise, another set is executed. The if statement is a form of compound statement. That is, it contains individual statements.

Task: Make an image appear on the canvas

Logic: HTML5 and JavaScript provide ways to draw images on canvas at specified x, y positions and with specified width and height.

Solution: Acquire (and modify as appropriate) image files representing the head and tail of a coin. Write the JavaScript that sets up Image objects and use the decision logic to draw one or the other on the canvas at a particular place.This is

var head = new Image();

head.src = "head.gif";

var tail = new Image();

tail.src="tail.gif";

In the clauses of the if statement, you will write either

if (Math.random()>.5) {

ctx.drawImage(head,mx,my, 100,100);

}

else {

ctx.drawImage(tail,mx,my,100, 100);

}

The calculation for mx and my are described in the next task.

Task: Implement the tossing of the coin.

Logic: You want the player to click on the canvas, indicated by an outline. HTML5 JavaScript provides a way to set up this event.

Solution: The event handling is done using the addEventListener method.

canvas1 = document.getElementById('canvas');

canvas1.addEventListener('click',toss,false);

The exact coordinates of the click will be used to position the image drawn. Unfortunately, this requires some browser-specific coding. The following works in the browsers I've tested (Chrome, Firefox). I'm told it works for Opera and Safari:

(Note: I have made some updates to this to take care of a new problem with Chrome.)

function toss(e) {

var mx;

var my;

if (!e) var e = window.event;

if (e.pageX || e.pageY) {

mx = e.pageX;

my = e.pageY;

} else if (e.clientX || e.clientY) {

mx = e.clientX + document.body.scrollLeft

+ document.documentElement.scrollLeft;

my = e.clientY + document.body.scrollTop

+ document.documentElement.scrollTop;

}

This example has some of this code in separate function, called getCoords.

The mx and my are the positions where the mouse cursor was located within the canvas.

Now keep in mind that the drawImage method positions an image using the upper left corner to be at the specified coordinates. Since I want the center of the image to appear at the point clicked by the mouse, I wrote code to adjust these values:

mx = mx -50;

my = my-50;

Background

After spending some time learning that computers do just what we tell them to do, you may ask how can we get 'the computer' to do something that appears to be random. Because random results are what is required for games and other applications, such as testing that a system works under a variety of conditions, the developers of languages such as JavaScript have developed what is called pseudo-random functions. The term 'pseudo' is meant to convey that in one sense, this is not random behavior at all. The code executed is as defined as the code for addition or subtraction. It is just that the result appears to be random. One common technique is to for the code to go to the place in memory that holds the time. This could be a sequence of bits (a bit is a 1 or a zero) typically 64 bits long. The next step is to take the middle 32 bits of this sequence, multiply it by itself, take the middle 32 bits of the answer and interpret this as a fraction between zero (including zero) and not more than one (not including the value 1).

You do not need to know or fully understand the particular algorithm used. To produce the coin toss program (and others), you just need to know that JavaScript has many mathematical functions available for your use. The format for calling these functions is as methods of the Math object. The one for random values, is Math.random(). Whenever you use this expression, JavaScript will generate a value greater than or equal to zero and less than one.

You will put the logic for coin tossing in a function defined within a script tag in the head section of the HTML document. This function is invoked through a call to addEventListener as a method to the canvas element. See code below for setting up the variable canvas1 to BE the canvas element.

Implementation

You need to do some preparation before testing any code, so you may as well do it right away. Prepare 2 image files:

  • head.gif
  • tail.gif

You can download images of coins. The terminology used is obverse and reverse as opposed to head and tail. Since my implementation was to make the coin images appear anywhere, including on top of each other, I decided that it would be nice if the surrounding for each round image was transparent, so a white background wouldn't appear on top of an image previously drawn as shown below:

This meant that after downloading the two images, which were jpg files, I opened them up in Corel Paint Shop Pro and used Export GIF Optimizer to save them with the white converted to be transparent. Adobe PhotoShop has a similar facility.

Make sure both of these files are in the same folder as the code you are about to produce.

We now describe the coding. We do this using the language of HTML. This is to help you understand the components of the file and not just copy and paste. Open up Text Pad or Text Wrangler or, if you have it Adobe Dreamweaver.

Create the standard boilerplate for an HTML5 page with a canvas element. I'm showing the DOCTYPE tag because some browsers may require it. I also included the instructions to Click to toss coin.

<!DOCTYPE html>

<html>

<head>

<title> </title>

<script>

</script>

</head>

<body onLoad="init();">

<canvas id="canvas" width="900" height="500">

Your browser doesn't support the HTML5 element canvas.

</canvas>

<br/>

Click to toss coin.

</html>

</body>

</html>

Think about what is needed in the code, that is, in the script element. There are two functions: init and toss and there are several variables. Listing the variables first, they are:

var cwidth = 900;

var cheight = 500;

var ctx;

var canvas1;

var head = new Image();

head.src = "head.gif";

var tail = new Image();

tail.src="tail.gif";

You can get away without using cwidth and cheight, that is, just using the constants.

The toss function has been shown already. I will repeat here the explanation for random processing and also the if statement.

The opening and closing parenthesis with the ev in-between indicate that this function expects a parameter. The parameter is set by JavaScript event handling. The code will use ev to determine the mouse coordinates. The code of the function goes after the opening curly bracket and before the closing curly bracket.

The code to find out the mouse coordinates starts with

if ( ev.layerX || ev.layerX == 0) {

You can read this as saying: does the ev object have an attribute called ev.layerX. If it doesn't, then ev.layerX will be interpreted as false. Since it also will be interpreted as false if it exists and is 0, then our code needs to check for that as well. If this clause fails, the our code tries something else, namely

else if (ev.offsetX || ev.offsetX == 0)

The effects of the compound if construction code is to store the values in the variables mx and my of where the mouse was clicked on the canvas.

The next statement of the toss function is another if statement. The following is what is called pseudo-code (not to be confused with pseudo-random). It is a melding of English and code to express what you want to happen.

if(condition determining head){

Do head thing}

else {

Do tail thing}

The if, opening and closing parentheses, else and the two sets of curly brackets are all JavaScript. What we need to fill in is the condition and the Do's.

The condition to be used here is to invoke the Math.random() method and compare it to a constant equal to one-half. If it is greater than or equal, then that will be a head. Note: when using if statements, you just put in a condition for one direction. Your code does not read anything like: If this is true than do this else if it is not true then do that.

The condition is

Math.random()>=.5

Remember to put this inside the parentheses.

Now we ask: what do we want to do if it is (to be) a head? The answer is that we will do something what will make sense when we write some code later on. This is a very typical situation. You cannot do everything all at once, so you need to be patient and say: I will get to this later. In our case, the do head thing is to draw the head image on the canvas at the calculated position and the tail thing is to draw the tail image on the canvas at the calculated position. By the way, in each case, we scale the image to 100 by 100. Look back at the definition of the toss function and see if you understand each line.

The init function, remember it is invoked by the action specified in the onLoad attribute in the body tag, is

function init(){

canvas1 = document.getElementById('canvas');

ctx = canvas1.getContext('2d');

canvas1.addEventListener('click',toss,false);

ctx.strokeRect(0,0,cwidth,cheight);

}

The init function sets the canvas1 and ctx variables. It then sets up the event handling for clicking on the canvas. Lastly, it draws an outline using the strokeRect method. The default color of black is fine.

You can and should put together the application: stick the var definitions and the two function definitions into the template. Try it out.

Now, here is how we can add keeping counts. Of course, we could use a form to output this information, but instead we will stick to writing on the canvas. For this, we will erase the canvas each time, though we could reserve space let's say a rectangle at the bottom of the canvas for the counts. The way we keep counts is to have two variables, I will call them internal variables, that start off

var hcount = 0;

var tcount = 0;

In the clause for displaying a head, we add the code

hcount++;

and in the clause for displaying a tail, we add the code

tcount++;

The ++ operator increments the variable by 1. Some people like it better than

hcount = hcount + 1;

because that seems illogical when you read the = sign as equal. You should read it 'gets assigned', but that is longer to say. The ++ operator probably produces faster code, but it probably is not significant in most examples. Computers are pretty fast.

Outside and below the if statements, we add the code

ctx.fillText("Head count "+String(hcount), 10,450);

ctx.filltext("Tail count "+String(tcount), 10, 475);

This puts the text indicated by the first parameter at location 10,450 and at 10,475.

You can use the default font, or put in a line like this in the init function:

ctx.font = 'bold 16px Georgia, Nevis, sans-serif';

This directs the font for text on the canvas to be bold and 16 pixels. If the Georgia font is available on the computer running the browser, then it is used; otherwise Nevis is used, and if it isn't available, then the default sans-serif font is used. This is the secure way to display text. You also can upload and/or reference a complete font on-line. Look that up on your own!

The complete code is at

Notice it uses photos that are not coin faces.