-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgameOfLife.js
132 lines (113 loc) · 3.64 KB
/
gameOfLife.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Grab the table DOM element
var table = document.getElementById("boardTable");
// Set the row numbers, column numbers
var NUMROWS = 15;
var NUMCOLS = 15;
var runId;
// the 2d array that will be used to hold the states of every cell
// and determine it's next generation
// must initialize with all 0s
var cells = [];
var i=0;
var j=0;
for (i ;i<NUMROWS; i++) {
cells[i] = [];
for (j=0; j<NUMCOLS; j++) {
cells[i][j] = 0;
}
}
// build the board
function bodyOnLoad() {
for (var i = 0; i < NUMROWS; i++) {
var newRow = table.insertRow();
for (var j = 0; j < NUMCOLS; j++) {
var newCell = newRow.insertCell();
newCell.onclick = function() {toggleAliveClass(this);};
}
}
}
// toggles the "alive" class of the cell which controls its color
function toggleAliveClass(cell) {
var classes = cell.className;
if ( classes.match(/(?:^|\s)alive(?!\S)/) ){
cell.className = classes.replace( /(?:^|\s)alive(?!\S)/g , '' );
} else {
cell.className += "alive";
}
}
// pull the current state of the board to a 2d array of ints
// with 0 representing dead and 1 representing alive
function pullTo2dArray() {
// get all cells with class "alive"
var aliveCells = table.querySelectorAll('td[class^="alive"]');
// set those cells to 1 in the 2d array
for (var i = 0; i < aliveCells.length; i++) {
var y = aliveCells[i].parentNode.rowIndex;
var x = aliveCells[i].cellIndex;
cells[y][x] = 1;
}
}
// returns a 2d arrary representing the next generation of the board given the
// rules:
// a live cell with 4 or more live neighbors dies
// a live cells with 1 or fewer neighbours dies
// a dead cell with exactly 3 neighbours births
// cells remains the same otherwise
function generate() {
var nextGen = [];
for (var i = 0; i < NUMROWS; i++) {
nextGen[i] = [];
for (var j = 0; j < NUMCOLS; j++) {
// count all 8 neighbours of the cell in the current gen
var neighbors = countNeighbors(cells, i, j);
var state = cells[i][j];
if (state == 0 && neighbors == 3) {
nextGen[i][j] = 1;
} else if (state == 1 && (neighbors <= 1 || neighbors >= 4)) {
nextGen[i][j] = 0;
} else {
nextGen[i][j] = state;
}
}
}
return nextGen;
}
// returns the amount of neighbours of a particular cell in a particular board
function countNeighbors(board, row, column) {
var neighbors = 0;
for (var i = -1; i <= 1; i++) {
for (var j = -1; j <= 1; j++) {
neighbors += board[(row+i+NUMROWS) % NUMROWS][(column+j+NUMCOLS)%NUMCOLS];
}
}
// minus the current cell's state because we counted it above^
neighbors -= cells[row][column]
return neighbors;
}
// updates the cells 2d array and the html table
function updateBoard() {
cells = generate();
updateTable();
}
function run() {
pullTo2dArray();
updateBoard();
runId = setInterval(updateBoard, 500);
}
function pause() {
clearInterval(runId);
}
// updates the html table according to the cells 2d array
function updateTable() {
// get all tabledata elements
var tds = table.getElementsByTagName("td");
// loop through the cells and apply their value to the class name of the
// corresponding cell
for (var row = 0; row < NUMROWS; row++){
for (var col = 0; col < NUMCOLS; col++) {
// if value is 1 set className to alive, otherwise set it to ""
state = cells[row][col];
tds[row*15 + col].className = (state ? "alive" : "");
}
}
}