<h1>O's & X's</h1>
<table>
<tr>
<td id="cell0"> </td>
<td id="cell1"> </td>
<td id="cell2"> </td>
</tr>
<tr>
<td id="cell3"> </td>
<td id="cell4"> </td>
<td id="cell5"> </td>
</tr>
<tr>
<td id="cell6"> </td>
<td id="cell7"> </td>
<td id="cell8"> </td>
</tr>
</table>
<p>
<input type="button" id="btnNewGame" value="New Game" />
</p>
body {
background-color: white;
color: black;
font-family: Arial, Helvetica, sans-serif;
}
h1 {
font-size: 28px;
}
table {
border-collapse: collapse;
}
td {
padding: 10px;
border: 3px #888 solid;
text-align: center;
font-size: 28px;
width: 20%;
font-family: Consolas, monospace
}
/* Set the border (top, right, bottom, left) of the cells */
#cell0 {
border-style: none solid solid none;
}
#cell1 {
border-style: none solid solid solid;
}
#cell2 {
border-style: none none solid solid;
}
#cell3 {
border-style: solid solid solid none;
}
#cell4 {
border-style: solid solid solid solid;
}
#cell5 {
border-style: solid none solid solid;
}
#cell6 {
border-style: solid solid none none;
}
#cell7 {
border-style: solid solid none solid;
}
#cell8 {
border-style: solid none none solid;
}
/* winning cells style */
.winningCell {
background-color: #f88;
}
/*
* The cells are numbered from 0 to 8 from top-left to bottom-right.
*/
window.onload = init; // run init() after the page is loaded
const NUM_CELLS = 9;
// A pattern is a 9-bit number where bit x represents cell x.
const WINNING_PATTERNS = new Array(0007, 0070, 0700, 0444, 0222, 0111, 0421, 0124); // Octal
var crossPattern, noughtPattern; // keep the plays so far
// "cross" is currently playing (boolean of true or false)
var crossPlaying;
// Initialize the game
function init() {
resetGame();
document.getElementById("btnNewGame").onclick = resetGame;
}
// Reset game by clearing all the cells and player's pattern
function resetGame() {
crossPattern = 0;
noughtPattern = 0;
crossPlaying = true;
for (var cellNum = 0; cellNum < NUM_CELLS; cellNum++) {
var elm = document.getElementById("cell" + cellNum);
elm.innerHTML = " "; // Clear content
elm.className = ""; // Reset the class, used by CSS
elm.onmousedown = play; // Attach mouse click handler
}
}
// Mouse-click handler
function play(evt) {
var thisCell;
if (evt) { // non-IE
thisCell = evt.target;
} else { // IE
thisCell = window.event.srcElement;
}
// Place the seed on the cell clicked and update the player's pattern
if (thisCell.innerHTML === " ") {
if (crossPlaying) {
thisCell.innerHTML = "x";
crossPattern |= Math.pow(2, thisCell.id.charAt(4));
} else {
thisCell.innerHTML = "o";
noughtPattern |= Math.pow(2, thisCell.id.charAt(4));
}
}
if (!checkWin()) {
// Continue playing
// Disable mouse click for this cell. This cell is no longer active
thisCell.onmousedown = null;
// toggling the current player
crossPlaying = !crossPlaying;
}
}
// Check if the current player wins the game
function checkWin() {
var theWinningPattern = -1;
var playerPattern;
if (crossPlaying) {
playerPattern = crossPattern;
} else {
playerPattern = noughtPattern;
}
// Check if playerPattern is one of the winning patterns
for (var i = 0; i < WINNING_PATTERNS.length; i++) {
if ((WINNING_PATTERNS[i] & playerPattern) === WINNING_PATTERNS[i]) {
theWinningPattern = WINNING_PATTERNS[i];
break;
}
}
// Change the class name of the cells of the winning pattern
// CSS class-selector displays them differently
if (theWinningPattern > -1) {
for (var cellNum = 0; cellNum < NUM_CELLS; cellNum++) {
var elm = document.getElementById("cell" + cellNum);
if (theWinningPattern & Math.pow(2, cellNum)) {
elm.className = "winningCell";
}
elm.onmousedown = null; // disable mouse click for all cells
}
return true;
} else {
return false;
}
}