TicTacToe in jQuery

As a demo application for a project of mine I wrote TicTacToe in Javascript using the jQuery framework.

I’ve added excessive comments to the code to provide an easy walk-through example on the jQuery/Javascript game. I’m in no way a JavaScript expert, there are a hundred different ways to program TicTacToe, and this code is far from clean but here it is!

There are just two files, the HTML page, and a page holding the javascript.

tictactoe.html


<html>

<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
<script src="tictactoe.js"></script>

<style>

table.board {
  border: 1px solid green; 
  height: 600px;
  width: 600px;
}

body {
  text-align: center;
  align: center;
}

td {
  height: 200px;
  width: 200px;
  text-align: center;
  vertical-align: middle;
  font-size: 100px;
  font-weight: bold;
  font-color: green;
  font-family: geniva, verdana, helvetica;
  border: 1px solid green;
}

#menu {
  text-align: center;
  position: absolute;
  width: 400;
  height: 400;
  margin-left: 100px;
  margin-top: 100px;
  border: 5px double red;
  display: none;
  vertical-align: middle;
  background-color: white;
}

#play_again {
  font-size: 20px;
  color: green;
}

</style>


</head>
<body>

<table border="0px" align="center">
<tr><td>
<div id="menu"></div>
<div id="board"></div>
</td></tr>
</table>

</body>


tictactoe.js

/* Main Game Handling class */
var TicTacToe = {
    turn: "O",  // Keeps a record of who's turn it is
    board: ["", "", "", "", "", "", "", "", "", ""],  // Keeps a record of the TicTacToe Board
    win: false, // records who won if the game is over
    
    /* Clears and starts a new game with a new board */
    restartGame: function() {
      // Draw the board
      var board_table = '<table class="board" border="0px" cellpadding="0px" cellspacing="0px" align="center"><tr><td id="ttt0">&nbsp;</td><td id="ttt1">&nbsp;</td><td id="ttt2">&nbsp;</td></tr><tr><td id="ttt3">&nbsp;</td><td id="ttt4">&nbsp;</td><td id="ttt5">&nbsp;</td></tr><tr><td id="ttt6">&nbsp;</td><td id="ttt7">&nbsp;</td><td id="ttt8">&nbsp;</td></tr></table>';
      $("#board").html(board_table);
      $("#menu").hide();
      
      // clear the board
      this.board = ["", "", "", "", "", "", "", "", "", ""];
      
      // Add on-click events to each of the boxes of the board
      $("#board td").click(function(e) {
          TicTacToe.move( e.target.id );
         });

    },

    /* Handles clicks spaces on the board */
    move: function(id) {
      var space = $("#" + id);  // Board space table element
      var num = id.replace("ttt", ""); // # representing the space on the board
    
      // If no one's gone there, and the game isn't over, go there!
      if (!this.board[num] && !this.win) {
        space.html( this.turn );
        this.board[num] = this.turn;
        this.nextTurn();  // End turn
      } 
    },

    /* Iterate turn and check if anyone one yet */
    nextTurn: function() {
      this.turn = (this.turn == "O") ? "X" : "O";
      this.win = this.check4Win();
      if (this.win) {
          this.endGame();
      }
    },

    /* Display who won and options for new games */
    endGame: function() {
    
      if (this.win == "Cat") {
          $("#menu").html("Cats Game.");
      } else {
          $("#menu").html(this.win + " wins!");
      }
      $("#menu").append("<div id='play_again'>Play Again</div>");
      
      // Button for playing again.
      $("#play_again").click(function () { TicTacToe.restartGame();  });
      $("#menu").show();
      this.win = false;
    
    },

    // If any of these patters of board spaces have all X's or all O's somebody won!
    wins: [[0,1,2], [3,4,5], [6,7,8], [0,3,6], [1,4,7], [2,5,8], [0,4,8], [6,4,2]],
    
    /* Check for whether someone won the game of it was a Cat's game. */
    check4Win: function() {
        
      // Loop through all possible winning combinations 
      for (k in this.wins){
        var pattern = this.wins[k];
        var p = this.board[pattern[0]] + this.board[pattern[1]] + this.board[pattern[2]];
        if (p == "XXX") {
          return "X";  // X Won!
        } else if (p == "OOO") {
          return "O";  // O Won!
        }
      }
      
      // Check if all spaces in the board are filled, then its a Cat's game
      var cnt = 0;
      for (s in this.board) {
        if (this.board[s]) { cnt+=1; }
      }
      if (cnt == 9) { 
        return "Cat";  // Cat's game!
      }
  }
};

$(document).ready(function() {
    
    // Start a game!
    TicTacToe.restartGame();
});

I’d originally setup the game on AppJet but unfortunately today they announced that they are closing down their framework and free hosting for a while to focus on one of their successful apps EtherPad. For at least the next month however you can play the game here, and play with the source code here. Feel free to use my code in any way.

If you do use the source for something, or have suggestions on improvements make sure to leave a comment.

Advertisements
11 comments
  1. Lue said:

    Hey, Dave!

    It’s me, Lue, if you remember! (Remember the canoe through Owl Lake in a test of our manhood?).

    I found your site trying to do some things with Plone (and lo and behold one site I found on Google had your name on it)…. nice JQuery usage there.. I was teaching myself Python by making myself a Yahtzee game clone, and then I put it through the Django framework (which I was/am still learning) and used JQuery to handle asynchronous requests and responses, along with user interaction…. it’s pretty slick (but still in-progress), and being a noob in web development it’s quite hacked together but definitely fun!

    • Hey Lue! Small world! Let me know if you have any questions on Django. I’ve been doing it full time for 2 years now. I love it. Send me a link to the game when its up :).

      • Lue said:

        Will do (if I ever get a new host that supports Python)… I may send you some questions regarding Django and Python… like what’s the best way to save a game object (I just serialized my game object using jsonpickle and threw that into a text field), or what’s the best approach to handling asynchronous requests (I was sending everything to one url and handling the post data to determine what action to take, though I’m thinking having separate views/urls for each type of action may have been easier to deal with…)… or things to do with authenticating users and organizing a site…

  2. Dave,
    I liked you object oriented approach πŸ™‚ I am developing a jigsaw game here at http://www.sabithpocker.com/ I want it as a plugin, but i failed to make it object oriented πŸ™‚ can you have a look at the code to give some guidelines? jigsaw,js is uncompressed πŸ™‚
    Regards,
    Sabith

    • It looks pretty cool and seems to work nicely as well!

      There’s no requirement to do it the OO way but its sometimes nice.

      If you were to do it the OO way you’d probably make an object for each box and have a list of the boxes.

      var boxes = []

      // populate the boxes with your Box Object
      for (i = 0; i < 50; i++) { boxes.push( new Box( i ); ) }

      Then put listeners on the boxes

      Box.onslide = function( droppedOntoBox ) {
      this.switchWith( droppedOntoBox );
      }

      But as I said its really not required and your code seems quite concise. If you're interested in learning best practices for java-script I highly recommend this book:

      http://www.amazon.com/Pro-JavaScript-Techniques-John-Resig/dp/1590597273/ref=sr_1_sc_3?ie=UTF8&qid=1284749040&sr=1-3-spell

      • Thank you for your reply, I lost track of this comment and accidentally stepped on it now while searching something πŸ™‚
        In the meanwhile i learned some object oriented programming , had a bad time understanding scopes of ‘this’ at different contexts, another problem was scope problem with set-timeout inside object, now feels relieved and easy with OO πŸ™‚
        I will look into ordering a copy of Resig’s book .

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s