Last active
January 2, 2016 05:59
-
-
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/
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
/*\ 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