Skip to content

Instantly share code, notes, and snippets.

@MikeBild
Last active December 19, 2015 08:29
Show Gist options
  • Save MikeBild/5926056 to your computer and use it in GitHub Desktop.
Save MikeBild/5926056 to your computer and use it in GitHub Desktop.
Tic Tac Toe - Event-Store - JavaScript
"use strict";
(function(exports){
exports.Aggregate = function(){
var events = [],
state = {};
return {
when: function(match){
state = match.$init ? match.$init : {};
for (var i = 0; i < events.length; i++) {
if(match[events[i].type] && events[i].data)
state = match[events[i].type](state, events[i].data);
}
return state;
},
emit: function(event){
events.push(event);
}
}
};
})(window.ES = {});
#board table {
border: 1px solid black;
}
#board table tr td{
width: 50px;
height: 50px;
border: 1px solid black;
text-align: center;
vertical-align: center;
}
<!DOCTYPE html>
<html>
<head>
<link href="css/style.css" media="all" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="board">
<table>
<tr>
<td id="31"></td>
<td id="32"></td>
<td id="33"></td>
</tr>
<tr>
<td id="21"></td>
<td id="22"></td>
<td id="23"></td>
</tr>
<tr>
<td id="11"></td>
<td id="12"></td>
<td id="13"></td>
</tr>
</table>
</div>
<div>
Round:
<div id="round"></div>
Player:
<div id="player"></div>
Situation:
<div id="situation"></div>
</div>
<script src="js/util.js" type="text/javascript"></script>
<script src="js/es.js" type="text/javascript"></script>
<script src="js/tttgame.js" type="text/javascript"></script>
<script src="js/tttview.js" type="text/javascript"></script>
</body>
</html>
"use strict";
(function(exports){
var game = new ES.Aggregate();
exports.game = game;
exports.checkGameState = function() {
var addTurn = function(state, event){
return function(turns){
turns.push(event.boardPosition);
return state;
};
};
var reviewWon = function(state, event){
return function(turns){
turns.sort();
for(var i in state.solutions){
var intersection = Util.intersect(turns, state.solutions[i]);
if(intersection.toString() === state.solutions[i].toString())
state.situation = "WON";
}
return state;
};
};
var reviewDraw = function(state, event){
if(state.round === 9 && state.situation !== "WON") state.situation = "DRAW";
return state;
};
var isClashedTurn = function(state, event){
return state.turnX.concat(state.turnO).indexOf(event.boardPosition) !== -1;
};
var togglePlayer = function(state, event){
if(state.situation === "WON" || state.situation === "DRAW") return state;
state.player = (state.player === "X") ? "O" : "X";
return state;
};
return game.when({
$init: {
player: "X",
situation: "START",
turnX: [],
turnO: [],
round: 0,
solutions: [
[11,12,13],
[21,22,23],
[31,32,33],
[11,22,33],
[13,22,31],
[11,21,31],
[12,22,32],
[13,23,33]
]
},
playedX: function(state, event){
if(isClashedTurn(state, event)) return state;
state.round++;
state.situation = "RUNNING";
addTurn(state, event)(state.turnX);
reviewWon(state, event)(state.turnX);
reviewDraw(state, event);
togglePlayer(state, event);
return state;
},
playedO: function(state, event){
if(isClashedTurn(state, event)) return state;
state.round++;
state.situation = "RUNNING";
addTurn(state, event)(state.turnO);
reviewWon(state, event)(state.turnO);
reviewDraw(state, event);
togglePlayer(state, event);
return state;
},
reseted: function(state, event){
state.round = 0;
state.turnO = [];
state.turnX = [];
state.player = "X";
state.situation = "START";
return state;
}
});
};
})(window.TTT = {});
"use strict";
(function initGame(){
var elements = Array.prototype.slice.call(document.getElementsByTagName("td"));
elements.forEach(function(element){
element.addEventListener('click', function(){
TTT.game.emit({ type:'played' + TTT.checkGameState().player, data: { boardPosition: this.id } });
refreshGame();
});
});
refreshGame();
})();
function refreshGame(){
var gameState = TTT.checkGameState();
resetBoard();
redrawBoard(gameState);
reviewGame(gameState);
};
function reviewGame(gameState){
if((gameState.situation === "WON" || gameState.situation === "DRAW")
&& confirm("New game?")) {
TTT.game.emit({type:'reseted', data: {}});
refreshGame();
};
};
function resetBoard(){
var elements = Array.prototype.slice.call(document.getElementsByTagName("td"));
elements.forEach(function(element){
element.innerText = "";
});
document.getElementById("situation").innerText = "";
document.getElementById("round").innerText = "";
document.getElementById("player").innerText = "";
};
function redrawBoard(gameState){
document.getElementById("situation").innerText = gameState.situation;
document.getElementById("round").innerText = gameState.round;
document.getElementById("player").innerText = gameState.player;
gameState.turnX.forEach(function(item){
document.getElementById(item).innerText = "X";
});
gameState.turnO.forEach(function(item){
document.getElementById(item).innerText = "O";
});
};
"use strict";
(function(exports){
exports.intersect = function (a, b){
var ai=0, bi=0;
var result = [];
while( ai < a.length && bi < b.length )
{
if (a[ai] < b[bi] ){ ai++; }
else if (a[ai] > b[bi] ){ bi++; }
else
{
result.push(a[ai]);
ai++;
bi++;
}
};
return result;
};
})(window.Util = {});
@MikeBild
Copy link
Author

MikeBild commented Jul 5, 2013

next step - distributed TicTacToe with node.js -> look here -> https://gist.github.com/MikeBild/e10f1c3e90ce4d17022a

@MikeBild
Copy link
Author

MikeBild commented Jul 7, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment