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 4, 2013

A) copy & paste into tictactoe.html
B) open tictactoe.html in your web browser (tested with Chrome)
C) Enter coordinates for your turn.
Board
31 32 33
21 22 23
11 12 13
D) play against a buddy and have fun!

@MikeBild
Copy link
Author

MikeBild commented Jul 5, 2013

strike C) play on a cool board since revision 3 ;)

@cessor
Copy link

cessor commented Jul 5, 2013

Der Code liest sich auf den ersten Blick hervorragend!

@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