Computer Science 180
Web Design
Fall 2011, Siena College
For this week's lab, you will gain much more experience with JavaScript programming.
You may work alone or with a partner on all parts of this lab.
Tic-Tac-Toe
For this task, you will create a web page using JavaScript to play a game of Tic-Tac-Toe. Start with this partially-completed document that lays out the playing board and contains one JavaScript function you'll need later.
Place the document into your folder for today's lab and open it up.
You should see a header and a blank Tic-Tac-Toe board. Note that each
table cell contains a non-breaking space - the
character which indicates that no "X" or "O" has been placed in
each cell yet.
Your first modification should be to add your name(s) to the comment at the top of the document. Remember, you should be including your name in a comment in every document you create!
"X"s and "O"s are to be placed by clicking in cells on the board. Your first real task is to get that to happen. You will need to write a JavaScript event handler function and add onclick attributes to each table cell that call this function to make this happen. Your function needs to take a parameter that indicates the id of the cell, so we can look it up using document.getElementById.
Initially, place only an "X" in any cell that is clicked. Only after you have verified that you can place an "X" into any cell should you worry about placing any "O"'s.
Alternating between "X" and "O" placement requires a bit more
effort. First, we will need to remember whose turn it is, so the next
selected cell gets the proper letter. Our mechanism to remember
information is to declare and use a global variable. Recall that a
global variable is one declared outside of any function, so it can
retain its value throughout the lifetime of the document. You will
need to initialize yours (let's call it turn) so that "X" goes
first. It will be most convenient if you use the strings "X"
and "O"
as the values for turn. Now, when a cell is
clicked, instead of always setting its innerHTML to "X"
,
you should set it to the value of your variable.
After placing an "X"
or "O"
based on the current value
of turn, its value must be swapped to the other possibility. We
can accomplish this as follows:
if (turn == "X") { turn = "O"; } else { turn = "X"; }
The condition here on our if statement is an equality comparison
(the ==
). If the value stored in turn is "X"
, it
evaluates to true, and we execute the statement in the first
{
}
block, which changes the value of turn to
"O"
. If turn was not "X"
, the else part is
executed, and turn becomes "X"
. This accomplishes the
desired switch. Be sure you do this after you use turn's
original value to place an "X"
or "O"
as appropriate.
Note: make sure you use ==
for the comparison for equality in
the if condition and =
for the assignment of new values to
variables.
After adding all of this, verify that your page alternates between
placing "X"
s and "O"
s.
Once that works, we'll take the next step toward a playable game by
making sure a player cannot choose an already-occupied cell. To do
this, we need to check the innerHTML of the cell to see if it
contains an "X"
or "O"
. If so, we will put up a message
that the cell is already occupied instead of setting the
innerHTML to the current value of turn and switching the
turn. Suppose we have given the name cell to the table cell
we've clicked on with a statement like:
var cell = document.getElementById(id);
(here, id is the name of your parameter specifying the id of
the cell that was clicked). We can then use the following conditional
to do something only in the case that the cell's innerHTML
contains either an "X"
or "O"
:
if (cell.innerHTML == "X" || cell.innerHTML == "O") { // handle case of an already-occupied cell return; }
Here, we have two equality comparisons grouped together with the
||
operator, which is the "or" operation. It means we should
execute the code inside the if when either the first equality is
true or the second is true. You will need to replace the
comment with some way to give feedback to the player that the move did
not occur and that some other cell should be chosen. (Suggestion: use
an alert for now). Having a return statement inside the
if means that the function will stop executing at that point.
This is exactly what we want, as the rest of the function is dealing
with placing a letter and updating the turn, all of which should
not occur in the case when an occupied cell was selected.
Next, we will add a message to the page that can be used to remind the players whose turn is next and indicate the error when someone attempts to use a cell that is already occupied (have this replace the alert you used before). Soon, we'll use it to indicate a win or draw.
To do this, add an element below the <table>
that you can use
for this purpose. At the start, it should contain a message like "X
goes first." Be sure to give it an id attribute so you can
look it up from your JavaScript function. In that function, set this
element's innerHTML to display appropriate messages such as whose
turn it is and to indicate when an already-occupied cell is selected.
Now, your game is playable, but there is no indication of a win or tie, nor does anything stop you from continuing play when someone has won. This will be the most complex addition, but the good news is that a function is provided that does much of the hard work.
Take a look at the checkGameStatus function. It retrieves the
value from each cell and places it into a local variable for easy
access throughout the function. Next, it checks for a win by the
"X" player by seeing if there is an "X"
in each cell in some
row, column, or diagonal. If it finds a winning case, it immediately
returns "X"
to indicate a win by player "X". It then does
the same to see if "O" has won. If there has not yet been a win,
perhaps the game has ended in a tie. We check this by seeing if all
cells contain something other than the " "
placed there at
the start. If this is the case, the function returns "draw"
.
Finally, if none of those things happened, the function returns
"none"
to indicate that the game should continue. Note that
this function makes extensive use of conditions that contain &&
operators - which mean "and". For example, the first condition
checks for a win by "X" in the first row by seeing if
topLeft == "X"
and topCenter == "X"
and
topRight == "X"
. If all three were true, the entire
expression evaluates to true and the function immediately returns
"X"
.
So this function will look at the current state of the board and
return one of four values: "X"
, "O"
, "draw"
, or
"none"
. We can use this in the event-handler function to
determine if any move should be allowed (i.e., that the game has not
already ended) or if a win or draw message should be displayed.
Take this approach: add a global variable called winner which
gets initialized to "none"
. At the start of your event
handler, you can use the statement
if (winner != "none") return;
to prevent it from doing anything in cases where some player has already won or the game has ended in a tie.
The only time that the value of winner can change is right after
an "X"
or "O"
has been placed on the board. So right
after doing that, we can update the value of winner to be the
return value of the checkGameStatus function:
winner = checkGameStatus();
After this, your function can check to see if winner has become
"X"
, "O"
or "draw"
, in which case the message
below the board should be updated and the function should return
immediately (to prevent the turn from changing and the message
about whose turn is next from being displayed).
This gives us a fully-functional game! Verify that your game plays properly before making our final addition for now: the ability to restart a game.
This last step involves adding a "Start Over" button that calls a
JavaScript function to reset the game to its initial state. This
involves setting the innerHTML of all cells to
,
resetting the winner variable to "none"
, the turn
variable to "X"
, and the message to indicate that "X" plays
first.
Extending the "Style Setting" Example
For this lab task, you will be looking more at the details of the restylesomethings.html example, then extending it a bit.
Make sure you understand how the addition of the checkboxes works and why styles for unchecked items are not applied when you click on elements of the page.
The first part of the task is to add at least two more style properties to the table of styles that can be applied.
The second part of the task is to "disable" the <select>
elements corresponding to those styles that would not be applied
because their checkbox is unchecked. A few things you will need to
use to make this happen:
<select>
element
by setting its disabled attribute to true or false.
When disabled is true, the element is "grayed out" and
cannot be modified.
Blastoff!
Your final task involves developing a simple "countdown" page. It should begin by displaying a large, black number 10 and a button labeled "Continue Countdown". Each time the button is clicked, the number displayed goes down by 1. When the number reaches 0, the number should be replaced with the word "Blastoff!" in large, red letters, and the label on the button should be replaced with "Start Over". When the button is pressed in this case, the display should again be a large, black number 10 and the button should again be labeled "Continue Countdown".
Submitting Your Work
Before 1:30 PM, Monday, November 7, 2011, submit your files for grading. There are three things you need to do to complete the submission: (i) make sure your pages are uploaded properly to the class web space and are available at your URI, (ii) update your main index on the class web space to have links to all documents you have created for this lab, and (iii) email a copy of your files to me at jteresco AT siena.edu. If you worked with a partner on any of the items, you need only upload to the account of one of the team members, but each team member should link to the pages on his or her own main index. Make sure all of your pages validate properly as XHTML Strict.
Grading Sheet
This lab is worth 30 points, which are distributed as follows:
> Feature | Value | Score |
Required Documents | ||
Tic-Tac-Toe | 8 | |
Style setting: two new style entries | 4 | |
Style setting: disable menus for unselected styles | 3 | |
Blastoff! | 9 | |
Style | ||
XHTML documents pass validation | 3 | |
Formatting of HTML text | 1 | |
Submission | ||
Main index updated | 1 | |
Email submission | 1 | |
Total | 30 | |