Python
SQL
JavaScript
Excel
Tableau

JavaScript

by Mike Thompson, 10/3/2015

In 2010 I took a couple web development classes at Edmonds Community College, in order to learn more about HTML, JavaScript, and PHP. One of the JavaScript assignments was to write a Tic-Tac-Toe game. The code that I wrote is shown here. If you would like to play this game, click on "odds & ends" on the top menu bar, then click on "tic tac toe" on the left menu bar.

The HTML below contains the form for the playing grid. There are three .png (Portable Network Graphics) image files for the three possible states of a square on the grid: blank, "X", and "O". The nine squares are numbered top-to-bottom, left-to-right from 0 through 8. When a mouse click occurs within a cell, the cellClick routine is called with the cell number as the parameter. There's a text output field below the playing grid for displaying messages like, "It's X's Turn." There's a reset button at the bottom for clearing the playing grid and restarting the game.

<div id="content">
<form action="" name="frmOptions" id="frmOptions">
<h1 align="center">Tic-Tac-Toe</h1>
<table border="1" cellpadding="2" align="center" bordercolor="#000000">
 <tr>
  <td><img src="B.png" width="100" height="100" alt="blank" name="0" onclick="return cellClick(0);" border="0"/></td>
  <td><img src="B.png" width="100" height="100" alt="blank" name="1" onclick="return cellClick(1);" /></td>
  <td><img src="B.png" width="100" height="100" alt="blank" name="2" onclick="return cellClick(2);" /></td>
 </tr>
 <tr>
  <td><img src="B.png" width="100" height="100" alt="blank" name="3" onclick="return cellClick(3);" /></td>
  <td><img src="B.png" width="100" height="100" alt="blank" name="4" onclick="return cellClick(4);" /></td>
  <td><img src="B.png" width="100" height="100" alt="blank" name="5" onclick="return cellClick(5);" /></td>
 </tr>
 <tr>
  <td><img src="B.png" width="100" height="100" alt="blank" name="6" onclick="return cellClick(6);" /></td>
  <td><img src="B.png" width="100" height="100" alt="blank" name="7" onclick="return cellClick(7);" /></td>
  <td><img src="B.png" width="100" height="100" alt="blank" name="8" onclick="return cellClick(8);" /></td>
 </tr>
</table>
<br />
<table border="0" cellpadding="2" align="center" bordercolor="#000000">
 <tr>
  <td valign="middle">
  <input type="text" name="txtTurn" readonly="readonly" id="txtTurn" value="X's Turn" size="5" /></td>
 </tr>
</table>
<br />
<table border="0" cellpadding="2" align="center" bordercolor="#000000">
 <tr>
  <td valign="middle">
  <input type="button" name="btnRestart" id="btnRestart" value="Restart Game" onclick="return resetGame();" /><br />
 </td>
 </tr>
</table>
</form>
</div>

<script type="text/javascript">
var lengthSrc = document.images[0].src.length;
</script>

The possible three-in-a-row winning combinations are stored in an array, and compared with the state of the playing grid each time a move is made in order to determine if there has been a winner. The contents of the text message field are used to determine whose turn it is.

<script type="text/javascript">

var rows = new Array(0,1,2,  3,4,5,  6,7,8,  0,3,6,  1,4,7,  2,5,8,  0,4,8,  2,4,6);
var threeInArow = null;
var winner = null;

/*----------
function cellClick(cellIndex)
purpose:  This is the event handler for mouse clicks in any of the 9 cells in the tic-tac-toe
    grid.   It considers whether to mark the cell clicked on with an X or and O, and
    then whether or not that results in three-in-a-row.
author:   Mike Thompson
date:   2/5/2010
parameters: cellIndex: zero-based index to the cell on which the mouse click occurred
return value: true
----------*/

function cellClick(cellIndex) {

  // If the cell clicked on is blank, then it's a valid move
  var rgxBlank = new RegExp("B[.]png$");
  var rgxReturn = document.images[cellIndex].src.match(rgxBlank);
  if (rgxReturn != null) {
    if (document.getElementById("txtTurn").value == "X's Turn") {
    document.images[cellIndex].src = document.images[cellIndex].src.replace(rgxBlank, "X.png");
    document.getElementById("txtTurn").value = "O's Turn";
    } else {
    document.images[cellIndex].src = document.images[cellIndex].src.replace(rgxBlank, "O.png");
    document.getElementById("txtTurn").value = "X's Turn";
    }
  }
  
  // Examine the three cells for each of the nine winning patterns. If all three
  // contain the identical, non-blank image ("X" or "O"), then we have a winner!
  for (var i = 0; i < (rows.length); i += 3) {
    threeInArow = document.images[rows[i]].src.substr(lengthSrc - 5, 1);
    if (threeInArow == "B") {
      threeInArow = null;
    }
    for (var j = 1; j < 3; j++) {
      if (threeInArow != document.images[rows[i + j]].src.substr(lengthSrc - 5, 1)) {
        threeInArow = null;
      }
    }
    if (threeInArow != null) {
      winner = threeInArow;
    }
  }
    
  if (winner != null) {
    alert("Congratulations player " + winner + "!");
  }
  return true;
}

/*----------
function resetGame()
purpose:  Reset the game to its initial state so that a new game may begin. Blank out all
    cells in the tic-tac-toe grid and reset the game state variables.
author:   Mike Thompson
date:   2/5/2010
parameters: none
return value: true
----------*/

function resetGame() {
  var rgxImage = new RegExp(".[.]png$");
  for (i = 0; i < 9; i++) {
    document.images[i].src = document.images[i].src.replace(rgxImage, "B.png");
  }
  document.getElementById("txtTurn").value = "X's Turn";
  threeInArow = null;
  winner = null;
  return true;
}

</script>

It is said that, "The more things change, the more they stay the same." Writing JavaScript brought some flashbacks of writing IBM CICS applications back in the mid 1980's at a finance company in downtown Seattle. When a user hit the Enter key on their 3270 terminal, CICS "woke up" your code and handed it a data structure representing the screen. Your first problem was to determine where you were at in the processing cycle. One did so with the help of a four-character screen ID, and by stashing state information in non-display fields on the screen. The game is exactly the same when you're writing JavaScript.

The little company where I was working at that time didn't have an online file dump utility, so I wrote one. I wrote it in the only language that we had a compiler for: COBOL! It was pretty fun project, actually. The screen I/O was easier to do in COBOL than in 3270 assembler, which was my only other language option. I managed bit manipulation by doing multiplication and division by powers of two, and determined the width, in bits, of the various COBOL data types by trial and error. I can't remember if I solved the problem of displaying the nibble (four bits) "1101" in hexadecimal as "D" by giving multiple type definitions for the same data item and adding the EBCDIC code for the character preceding "A" or "0", or by doing a table lookup. I do remember that it was a fun puzzle to solve, that I learned a lot, and that the result was a handy utility that was used by myself and others on the programming staff.

Doug Walker, with whom I had stayed in touch with since we had worked together at Western Data, did something even more fun with COBOL around that time: he wrote a calculator! In those days he was writing business software on HP3000 minicomputers, a machine that had a stack architecture. By de-compiling COBOL code, Doug was able to determine how to use procedure calls and GO TO statements to get the stack to do what he wanted it to, and then was able to write a recursive-descent arithmetic expression parser in COBOL, of all languages. Hey, if all you've got is lemons, then why not make some lemonade?!