JSFiddle - React, Tailwind, and code Playground
HTML
<body>
<div id="canvas">
<div class="top row">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
<div class="middle row">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
<div class="bottom row">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
</div>
<div id="winner">
WINNER!
</div>
<div id="draw">
DRAW!
</div>
</body>
CSS
body {
font-size: 32px;
font-family: sans-serif;
width: 295px;
margin: 1em auto;
}
#canvas {
width: 296px;
float: left;
}
.row {
width: 296px;
float: left;
}
.row div {
width: 95px;
padding-top: 25px;
height: 61px;
float: left;
text-align: center;
}
.top {
border-bottom: 5px solid black;
}
.bottom {
border-top: 5px solid black;
}
.left {
border-right: 5px solid black;
}
.right {
border-left: 5px solid black;
}
#draw, #winner {
display: none;
text-align: center;
padding-top: 0.5em;
clear: both;
}
JavaScript
const X = "X";
const O = "O";
const WINNING_STATE = {
NONE: 0,
X: 1,
O: 2,
DRAW: 3,
}
class Model {
constructor() {
this.gameState = [];
this.isXTurn = true;
this.moveCount = 0;
let i;
for (i = 0; i < 3; i++) {
this.gameState[i] = [];
}
}
getSquare(row, col) {
return this.gameState[col][row]
}
selectX(row, col) {
this.selectSquare(X, row, col);
}
selectO(row, col) {
this.selectSquare(O, row, col);
}
selectSquare(type, row, col) {
if (type != X && type != O) {
throw new TypeError("Invalid type: " + type)
}
if (row < 0 || row > 2 || col < 0 || col > 2) {
throw new RangeError("Invalid range: " + row + ", " + col)
}
this.gameState[col][row] = type;
this.moveCount++;
// this.printGameState();
}
printGameState() {
let i;
for (i = 0; i < 3; i++) {
console.log(this.gameState[i]);
}
}
}
class Controller {
constructor() {
this.model = new Model();
this.winningState = WINNING_STATE.NONE;
this.squares = document.querySelectorAll(".row div");
this.bindAllSquareClicks();
}
winningStateForXAtPosition(row, col) {
return this.winningStateForTypeAtPosition(X, row, col);
}
winningStateForOAtPosition(row, col) {
return this.winningStateForTypeAtPosition(O, row, col);
}
winningStateForTypeAtPosition(type, row, col) {
let gameState = this.model.gameState // Convenience
// Check horizontally
let col_;
for (col_ = 0; col_ < 3; col_++) {
if (type != this.model.getSquare(row, col_)) {
break;
}
}
if (col_ == 3) {
return WINNING_STATE[type]
}
// Check vertically
let row_;
for (row_ = 0; row_ < 3; row_++) {
if (type != this.model.getSquare(row_, col)) {
break;
}
}
if (row_ == 3) {
return WINNING_STATE[type]
}
// Check diagonal
if (row == col) {
let rowcol;
for (rowcol = 0; rowcol < 3;...