Skip to content

Instantly share code, notes, and snippets.

@BlackthornYugen
Last active January 2, 2016 05:59
Show Gist options
  • Save BlackthornYugen/8260675 to your computer and use it in GitHub Desktop.
Save BlackthornYugen/8260675 to your computer and use it in GitHub Desktop.
A JS version of Conway's Game of Life SRC: https://jsbin.com/OqaYefOl/
/*\ A JS version of Conway's Game of Life v0.14
|*|
|*| Revision History
|*| 2013-12-30 - 1605: Setup countElementsFrom to keep track of coords.
|*| 2013-12-30 - 1743: Added statics on hover.
|*| 2014-01-02 - 0433: Began refactoring code to OOP.
|*| 2014-01-02 - 0606: Making signifigent changes to scope on events.
|*| 2014-01-02 - 2157: Changing code logic to optimize speed. Current method is extreamly wastefull. Checking ajacent cells of cells that are no where near living cells.
|*| 2014-01-03 - 1240: Milestone .12 got it mostly working but auto-step needs to be a seperate function.
|*| 2014-01-04 - 1309: Built autostep dealie.
|*| 2014-01-04 - 1604: Created gist; working to fix zoom stuff on android.
|*| 2014-01-04 - 1652: Gave up on fixing zoom the way I want it. Added hotkeys and updated instructions.
\*/
$(function(){
$('body').append(generateTable(25, 25));
game = new GameOfLife($("table")[0]);
timer = new TimeFunction(game.actionElements,+$("#stepDelay").val(),game);
/*\
|*| Initialize DOM events.
\*/
$("#stepOnce").click(function (){
game.actionElements();
});
$("#stepAuto").click(function (){
var enabled = timer.toggle();
if(enabled) {
$(this).css("background-color", "lightgreen");
} else {
$(this).css("background-color", "");
}
$("#stepOnce").attr("disabled",enabled);
});
$("#stepDelay").change(function (){
timer.setFreq(+$("#stepDelay").val());
});
var that = game;
var $td = $(that.table).find("td");
$td.on("click", function (){
$(this).toggleClass("clicked");
});
$td.on("mouseover", function (){
var $e = $(this);
var adj = that.countAdjacentElements(this);
$("span.location").text("(" +
($e.data("x") + 1) + "," +
($e.parent().siblings().length - $e.data("y") + 1) +
")");
$("span.count").text(adj);
$("span.pluralCount").text(adj == 1 ? "" : "s");
});
$(document).keypress(function (event){
var $auto = $( "#stepAuto" );
var $once = $( "#stepOnce" );
if ( event.which === 13) {
$auto.trigger( "click" );
event.preventDefault();
} else if (event.which === 32 && $once.attr("disabled") !== "disabled") {
$once.trigger( "click" );
event.preventDefault();
}
});
});
/*\
|*| GENERATE TABLE FUNCTION
\*/
function generateTable(width, height) {
var $table = $("<table>");
for(var y = 0; y < height; y++){
var $tableRow = $("<tr>");
for (var x = 0; x < width; x++){
$tableRow.append($("<td>")
.data("adjacent", 0)
.data("x",x).data("y",y)
);
}
$table.append($tableRow);
}
return $table;
}
/*\
|*| TIMER CONSTRUCTOR
\*/
function TimeFunction(func, freq, scope) {
this.func = func;
this.freq = freq;
this.scope = scope;
this.interval = 0;
this.start = function() {
clearTimeout(this.interval);
$.proxy(this.func,this.scope)();
this.interval = setTimeout($.proxy(this.start,this),this.freq);
return this;
};
this.stop = function() {
clearTimeout(this.interval);
this.interval = 0;
};
this.toggle = function() {
if (this.interval === 0){
this.start();
return true;
} else {
this.stop();
return false;
}
};
this.setFreq = function(sec) {
this.stop();
this.freq = sec;
this.interval = setTimeout($.proxy(this.start,this),this.freq);
return this;
};
}
/*\
|*| GAME OF LIFE CONSTRUCTOR
\*/
function GameOfLife(table){
this.table = table; // A table with at least one row & col
this.adjacentCells = [ [-1,-1], [0,-1], [1,-1], // An array of relative
[-1, 0], [1, 0], // positions for ajacent
[-1, 1], [0, 1], [1, 1] ]; // cells.
this.actionElements = function (){
console.log('actionElements');
var checked = [];
var that = this;
$(this.table).find("td").data("adjacent",0).text('');
$(this.table).find("td.clicked").each(function (n, e){
var $e = $(e);
var adjacentElements = that.returnAdjacentElements(e);
checked.push(e);
for (var i=0; i < adjacentElements.length; i++){
$(adjacentElements[i]).data().adjacent++;
}
});
$(this.table).find("td:not(.clicked)").filter(function (){
return 3 === $(this).data("adjacent");
}).each(function (n, e){
$(e).toggleClass('clicked');
});
for(var i = 0; i < checked.length; i++){
var $e = $(checked[i]);
var adj = $e.data("adjacent");
if(3 != adj && 2 != adj){
$e.toggleClass("clicked");
}
}
};
this.countAdjacentElements = function (element){
var cellCount = 0;
var adjacentElements = this.returnAdjacentElements(element);
for (var i=0; i < adjacentElements.length; i++){
var $adjacentElement = $(adjacentElements[i]);
if ($adjacentElement.hasClass("clicked")) cellCount++;
}
return cellCount;
};
this.returnAdjacentElements = function (element){
returnArray = [];
var xPos = $(element).prevAll().length;
var xCount = $(element).siblings().length;
var yPos = $(element).parent().prevAll().length;
var yCount = $(element).parent().siblings().length;
for (var i=0; i<this.adjacentCells.length; i++){
var x = xPos + this.adjacentCells[i][0];
var y = yPos + this.adjacentCells[i][1];
if(x>=0 && y>=0 && x <= xCount && y <= yCount){
returnArray.push($(element).parents(":eq(1)")
.children("tr").eq(y).children("td").eq(x)[0]);
}
}
return returnArray;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment