I made this code myself and was experimenting with making buttons from a table, and decided to make a game of Tic-Tac-Toe with it.
The code loads from JSON a grid, and then makes a Tic-Tac-Toe game with populated as a 3x3 table with empty spaces. This takes place in the getJSON. Inside each cell are events, namely the click event, which simulates a turn.
It is complete with a home page and styling. Perhaps the most notable feature is the border-style: inset
and border-style: outset
, which make td
s appear as buttons, which can be utilized with jQuery.
// retrieve game state from json, and append a clickable tic tac toe table
$.getJSON('asset/json/tictactoe.json',
function(data)
{
// add a table to the grid (3x3)
$("#grid").append('<table/>');
var table = $("#grid").find("table");
for (var i=0; i<data.length; ++i)
{
// add a row in the table
$(table).append('<tr/>');
for (var j=0; j<data[i].length; ++j)
{
var row = $(table).children()[i];
$(row).append('<td/>');
var td = $(row).children()[j];
// add the 2D grid from JSON object
$(td).html(data[i][j]);
// add id to attribute
//this is used to assist in checking game state for the end of the game
$(td).attr("id","b"+i+j);
// add hover feature to table buttons
$(td).hover(function() { $(this).toggleClass("hovered"); });
// make table buttons clickable
$(td).click(
function()
{
var X = " X "; var O = " O "; var V = " "; var D = "DRAW!";
if (($("#winner").html() == X) || ($("#winner").html() == O) || ($("#winner").html() == D))
{
window.alert('game is complete.');
return true;
}
if ($(this).html() != V)
{
window.alert('square is occupied.');
return false;
}
var turn = $("#turn").html();
$(this).html(turn);
turn = (turn == O) ? X : O;
$("#turn").html(turn);
$(this).toggleClass("pushed");
$("#winner").trigger("click");
}
);
}
}
}
);
// check game state when trigger or if user clicks the winner box
$("#winner").click(
function() {
// initialize variables
var board = [[[],[],[]],[[],[],[]],[[],[],[]]];
var X = " X "; var O = " O "; var V = " "; var D = "DRAW!";
// if there is already a winner, or it is drawn, then do not bother
if (($("#winner").html() == X) || ($("#winner").html() == O) || ($("#winner").html() == D)) return true;
// retrieve board from td's. could be done by grabbing #grid
var occupied = 0;
for (var i=0; i<board.length; ++i)
for (var j=0; j<board[i].length; ++j)
board[i][j] = $("#"+"b"+i+j).html();
var winner = V;
// check for non-diagonal wins
for (var i=0; i<board.length; ++i)
{
// horizontally
if (((board[i][0] == X) || (board[i][0] == O)) && ((board[i][0] == board[i][1]) && (board[i][1] == board[i][2])))
{
winner = board[i][0];
break;
}
// vertically
if (((board[0][i] == X) || (board[0][i] == O)) && (board[0][i] == board[1][i]) && (board[1][i] == board[2][i]))
{
winner = board[0][i];
break;
}
}
// if no winner yet
if (winner == V)
{
// check for diagonal wins
if ((board[0][0] == X) || (board[0][0] == O))
if ((board[0][0] == board[1][1]) && (board[1][1] == board[2][2]))
winner = board[0][0];
if ((board[0][2] == X) || (board[0][2] == O))
if ((board[0][2] == board[1][1]) && (board[1][1] == board[2][0]))
winner = board[0][2];
}
// is there a winner?
if (winner != V)
{
$("#turn").html("Game Over");
$("#winner").html(winner);
return true;
}
// count how many suqares are occupied
var occupied = 0;
for (var i=0; i<board.length; ++i)
for (var j=0; j<board[i].length; ++j)
if ((board[i][j] == X) || (board[i][j] == O)) ++occupied;
// is the game drawn?
if (occupied >= 9)
{
$("#turn").html("Game Over");
$("#winner").html(D);
return true;
}
}
);
#grid table {
border-spacing: 3px;
}
#grid table > tr > td {
border-color: #92A5BD;
border-width: 3px;
border-style: outset;
padding: 3px;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 16px;
text-align: center;
cursor: pointer;
}
#grid table > tr > td.hovered {
border-style: inset; /* button appearance w/ border style */
background-color: #F99;
}
#grid table > tr > td.pushed {
border-style: outset; /* button appearance w/ border style */
background-color: #999;
}
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="asset/css/tictactoe.css">
</head>
<body>
<div id="grid"><!-- tic-tac-toe board is populated here -->
</div>
<div id="game">
<table>
<tr>
<td>Turn: </td><td id="turn"> X </td>
</tr>
<tr>
<td>Winner: </td><td id="winner"> </td>
</tr>
</table>
</div>
<!--
<div>
<textarea id="debug" rows="10" cols="50"></textarea>
</div>
-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="asset/js/jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="asset/js/tictactoe.js"></script>
</body>
</html>
It can perhaps be improved upon with gifs, and externalizing variables somehow, namely the X,O,V,D variables. Also, what is annoying is that the td's don't stay still when the text inside changes, which is why I used the "nbsp" character. A better choice could've been made. All in all, decent result.