Created
April 28, 2019 14:32
-
-
Save aire-con-gas/74db149e1dbeb69c3b02c8434c025b2b to your computer and use it in GitHub Desktop.
JS Bin // source https://jsbin.com/xukefoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width"> | |
<title>JS Bin</title> | |
<style id="jsbin-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; | |
} | |
</style> | |
</head> | |
<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> | |
<script id="jsbin-javascript"> | |
"use strict"; | |
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
var X = "X"; | |
var O = "O"; | |
var WINNING_STATE = { | |
NONE: 0, | |
X: 1, | |
O: 2, | |
DRAW: 3 | |
}; | |
var Model = (function () { | |
function Model() { | |
_classCallCheck(this, Model); | |
this.gameState = []; | |
this.isXTurn = true; | |
this.moveCount = 0; | |
var i = undefined; | |
for (i = 0; i < 3; i++) { | |
this.gameState[i] = []; | |
} | |
} | |
_createClass(Model, [{ | |
key: "getSquare", | |
value: function getSquare(row, col) { | |
return this.gameState[col][row]; | |
} | |
}, { | |
key: "selectX", | |
value: function selectX(row, col) { | |
this.selectSquare(X, row, col); | |
} | |
}, { | |
key: "selectO", | |
value: function selectO(row, col) { | |
this.selectSquare(O, row, col); | |
} | |
}, { | |
key: "selectSquare", | |
value: function 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(); | |
} | |
}, { | |
key: "printGameState", | |
value: function printGameState() { | |
var i = undefined; | |
for (i = 0; i < 3; i++) { | |
console.log(this.gameState[i]); | |
} | |
} | |
}]); | |
return Model; | |
})(); | |
var Controller = (function () { | |
function Controller() { | |
_classCallCheck(this, Controller); | |
this.model = new Model(); | |
this.winningState = WINNING_STATE.NONE; | |
this.squares = document.querySelectorAll(".row div"); | |
this.bindAllSquareClicks(); | |
} | |
// --- | |
_createClass(Controller, [{ | |
key: "winningStateForXAtPosition", | |
value: function winningStateForXAtPosition(row, col) { | |
return this.winningStateForTypeAtPosition(X, row, col); | |
} | |
}, { | |
key: "winningStateForOAtPosition", | |
value: function winningStateForOAtPosition(row, col) { | |
return this.winningStateForTypeAtPosition(O, row, col); | |
} | |
}, { | |
key: "winningStateForTypeAtPosition", | |
value: function winningStateForTypeAtPosition(type, row, col) { | |
var gameState = this.model.gameState; // Convenience | |
// Check horizontally | |
var col_ = undefined; | |
for (col_ = 0; col_ < 3; col_++) { | |
if (type != this.model.getSquare(row, col_)) { | |
break; | |
} | |
} | |
if (col_ == 3) { | |
return WINNING_STATE[type]; | |
} | |
// Check vertically | |
var row_ = undefined; | |
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) { | |
var rowcol = undefined; | |
for (rowcol = 0; rowcol < 3; rowcol++) { | |
if (type != this.model.getSquare(rowcol, rowcol)) { | |
break; | |
} | |
} | |
if (rowcol == 3) { | |
return WINNING_STATE[type]; | |
} | |
} | |
// Check anti-diagonal | |
if (row + col == 2) { | |
var rowcol = undefined; | |
for (rowcol = 0; rowcol < 3; rowcol++) { | |
if (type != this.model.getSquare(rowcol, 2 - rowcol)) { | |
break; | |
} | |
} | |
if (rowcol == 3) { | |
return WINNING_STATE[type]; | |
} | |
} | |
if (this.model.moveCount == 9) { | |
return WINNING_STATE.DRAW; | |
} | |
return WINNING_STATE.NONE; | |
} | |
}, { | |
key: "bindAllSquareClicks", | |
value: function bindAllSquareClicks() { | |
var _this = this; | |
var i = undefined; | |
var _loop = function () { | |
var that = _this; | |
var ii = i; | |
_this.squares[i].addEventListener("click", function squareClicked() { | |
if (WINNING_STATE.NONE != that.winningState) { | |
this.removeEventListener("click", squareClicked); | |
return; | |
} | |
var row = ii % 3; | |
var col = Math.floor(ii / 3); | |
if (that.model.isXTurn) { | |
that.model.selectX(row, col); | |
that.drawX(row, col); | |
that.winningState = that.winningStateForXAtPosition(row, col); | |
if (WINNING_STATE.X == that.winningState) { | |
that.drawXAsWinning(); | |
} | |
} else { | |
that.model.selectO(row, col); | |
that.drawO(row, col); | |
that.winningState = that.winningStateForOAtPosition(row, col); | |
if (WINNING_STATE.O == that.winningState) { | |
that.drawOAsWinning(); | |
} | |
} | |
if (WINNING_STATE.DRAW == that.winningState) { | |
that.drawDraw(); | |
} | |
that.model.isXTurn = !that.model.isXTurn; | |
this.removeEventListener("click", squareClicked); | |
}); | |
}; | |
for (i = 0; i < 9; i++) { | |
_loop(); | |
} | |
} | |
}, { | |
key: "drawX", | |
value: function drawX(row, col) { | |
this.squares[col * 3 + row].innerHTML = X; | |
} | |
}, { | |
key: "drawO", | |
value: function drawO(row, col) { | |
this.squares[col * 3 + row].innerHTML = O; | |
} | |
}, { | |
key: "drawXAsWinning", | |
value: function drawXAsWinning() { | |
document.querySelector("#winner").style.display = "block"; | |
} | |
}, { | |
key: "drawOAsWinning", | |
value: function drawOAsWinning() { | |
document.querySelector("#winner").style.display = "block"; | |
} | |
}, { | |
key: "drawDraw", | |
value: function drawDraw() { | |
document.querySelector("#draw").style.display = "block"; | |
} | |
}]); | |
return Controller; | |
})(); | |
new Controller(); | |
</script> | |
<script id="jsbin-source-css" type="text/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; | |
}</script> | |
<script id="jsbin-source-javascript" type="text/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; rowcol++) { | |
if (type != this.model.getSquare(rowcol, rowcol)) { | |
break; | |
} | |
} | |
if (rowcol == 3) { | |
return WINNING_STATE[type] | |
} | |
} | |
// Check anti-diagonal | |
if (row + col == 2) { | |
let rowcol; | |
for (rowcol = 0; rowcol < 3; rowcol++) { | |
if (type != this.model.getSquare(rowcol, 2 - rowcol)) { | |
break; | |
} | |
} | |
if (rowcol == 3) { | |
return WINNING_STATE[type] | |
} | |
} | |
if (this.model.moveCount == 9) { | |
return WINNING_STATE.DRAW | |
} | |
return WINNING_STATE.NONE | |
} | |
bindAllSquareClicks() { | |
let i; | |
for (i = 0; i < 9; i++) { | |
let that = this; | |
let ii = i; | |
this.squares[i].addEventListener("click", function squareClicked() { | |
if (WINNING_STATE.NONE != that.winningState) { | |
this.removeEventListener("click", squareClicked); | |
return; | |
} | |
let row = ii % 3; | |
let col = Math.floor(ii / 3); | |
if (that.model.isXTurn) { | |
that.model.selectX(row, col); | |
that.drawX(row, col); | |
that.winningState = that.winningStateForXAtPosition(row, col) | |
if (WINNING_STATE.X == that.winningState) { | |
that.drawXAsWinning() | |
} | |
} else { | |
that.model.selectO(row, col); | |
that.drawO(row, col); | |
that.winningState = that.winningStateForOAtPosition(row, col) | |
if (WINNING_STATE.O == that.winningState) { | |
that.drawOAsWinning() | |
} | |
} | |
if (WINNING_STATE.DRAW == that.winningState) { | |
that.drawDraw() | |
} | |
that.model.isXTurn = !that.model.isXTurn; | |
this.removeEventListener("click", squareClicked); | |
}); | |
} | |
} | |
drawX(row, col) { | |
this.squares[col * 3 + row].innerHTML = X; | |
} | |
drawO(row, col) { | |
this.squares[col * 3 + row].innerHTML = O; | |
} | |
drawXAsWinning() { | |
document.querySelector("#winner").style.display = "block" | |
} | |
drawOAsWinning() { | |
document.querySelector("#winner").style.display = "block" | |
} | |
drawDraw() { | |
document.querySelector("#draw").style.display = "block" | |
} | |
} | |
// --- | |
new Controller();</script></body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
var X = "X"; | |
var O = "O"; | |
var WINNING_STATE = { | |
NONE: 0, | |
X: 1, | |
O: 2, | |
DRAW: 3 | |
}; | |
var Model = (function () { | |
function Model() { | |
_classCallCheck(this, Model); | |
this.gameState = []; | |
this.isXTurn = true; | |
this.moveCount = 0; | |
var i = undefined; | |
for (i = 0; i < 3; i++) { | |
this.gameState[i] = []; | |
} | |
} | |
_createClass(Model, [{ | |
key: "getSquare", | |
value: function getSquare(row, col) { | |
return this.gameState[col][row]; | |
} | |
}, { | |
key: "selectX", | |
value: function selectX(row, col) { | |
this.selectSquare(X, row, col); | |
} | |
}, { | |
key: "selectO", | |
value: function selectO(row, col) { | |
this.selectSquare(O, row, col); | |
} | |
}, { | |
key: "selectSquare", | |
value: function 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(); | |
} | |
}, { | |
key: "printGameState", | |
value: function printGameState() { | |
var i = undefined; | |
for (i = 0; i < 3; i++) { | |
console.log(this.gameState[i]); | |
} | |
} | |
}]); | |
return Model; | |
})(); | |
var Controller = (function () { | |
function Controller() { | |
_classCallCheck(this, Controller); | |
this.model = new Model(); | |
this.winningState = WINNING_STATE.NONE; | |
this.squares = document.querySelectorAll(".row div"); | |
this.bindAllSquareClicks(); | |
} | |
// --- | |
_createClass(Controller, [{ | |
key: "winningStateForXAtPosition", | |
value: function winningStateForXAtPosition(row, col) { | |
return this.winningStateForTypeAtPosition(X, row, col); | |
} | |
}, { | |
key: "winningStateForOAtPosition", | |
value: function winningStateForOAtPosition(row, col) { | |
return this.winningStateForTypeAtPosition(O, row, col); | |
} | |
}, { | |
key: "winningStateForTypeAtPosition", | |
value: function winningStateForTypeAtPosition(type, row, col) { | |
var gameState = this.model.gameState; // Convenience | |
// Check horizontally | |
var col_ = undefined; | |
for (col_ = 0; col_ < 3; col_++) { | |
if (type != this.model.getSquare(row, col_)) { | |
break; | |
} | |
} | |
if (col_ == 3) { | |
return WINNING_STATE[type]; | |
} | |
// Check vertically | |
var row_ = undefined; | |
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) { | |
var rowcol = undefined; | |
for (rowcol = 0; rowcol < 3; rowcol++) { | |
if (type != this.model.getSquare(rowcol, rowcol)) { | |
break; | |
} | |
} | |
if (rowcol == 3) { | |
return WINNING_STATE[type]; | |
} | |
} | |
// Check anti-diagonal | |
if (row + col == 2) { | |
var rowcol = undefined; | |
for (rowcol = 0; rowcol < 3; rowcol++) { | |
if (type != this.model.getSquare(rowcol, 2 - rowcol)) { | |
break; | |
} | |
} | |
if (rowcol == 3) { | |
return WINNING_STATE[type]; | |
} | |
} | |
if (this.model.moveCount == 9) { | |
return WINNING_STATE.DRAW; | |
} | |
return WINNING_STATE.NONE; | |
} | |
}, { | |
key: "bindAllSquareClicks", | |
value: function bindAllSquareClicks() { | |
var _this = this; | |
var i = undefined; | |
var _loop = function () { | |
var that = _this; | |
var ii = i; | |
_this.squares[i].addEventListener("click", function squareClicked() { | |
if (WINNING_STATE.NONE != that.winningState) { | |
this.removeEventListener("click", squareClicked); | |
return; | |
} | |
var row = ii % 3; | |
var col = Math.floor(ii / 3); | |
if (that.model.isXTurn) { | |
that.model.selectX(row, col); | |
that.drawX(row, col); | |
that.winningState = that.winningStateForXAtPosition(row, col); | |
if (WINNING_STATE.X == that.winningState) { | |
that.drawXAsWinning(); | |
} | |
} else { | |
that.model.selectO(row, col); | |
that.drawO(row, col); | |
that.winningState = that.winningStateForOAtPosition(row, col); | |
if (WINNING_STATE.O == that.winningState) { | |
that.drawOAsWinning(); | |
} | |
} | |
if (WINNING_STATE.DRAW == that.winningState) { | |
that.drawDraw(); | |
} | |
that.model.isXTurn = !that.model.isXTurn; | |
this.removeEventListener("click", squareClicked); | |
}); | |
}; | |
for (i = 0; i < 9; i++) { | |
_loop(); | |
} | |
} | |
}, { | |
key: "drawX", | |
value: function drawX(row, col) { | |
this.squares[col * 3 + row].innerHTML = X; | |
} | |
}, { | |
key: "drawO", | |
value: function drawO(row, col) { | |
this.squares[col * 3 + row].innerHTML = O; | |
} | |
}, { | |
key: "drawXAsWinning", | |
value: function drawXAsWinning() { | |
document.querySelector("#winner").style.display = "block"; | |
} | |
}, { | |
key: "drawOAsWinning", | |
value: function drawOAsWinning() { | |
document.querySelector("#winner").style.display = "block"; | |
} | |
}, { | |
key: "drawDraw", | |
value: function drawDraw() { | |
document.querySelector("#draw").style.display = "block"; | |
} | |
}]); | |
return Controller; | |
})(); | |
new Controller(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment