I'm a beginner at coding and the past days I tried to write the famous "Conway's Game of Life" in Angular.js. Right now I'm done with the code and the game works. But if the size of the playground grid gets too big (e.g. 100x100 cells), my program is kind of slow. I wanted to ask you where I could improve my code to make it run more quickly. It would be great for me to see what I have could done in a better way to learn from it.
The following code creates the grid for the playing field and gives the cells their coordinates and alive status:
$scope.createGrid = function(width,height){ // Spielfeld erzeugen
$scope.playingField = {
width:width,
height:height,
data:[]
};
for( var r = 0 ; r < width; r++){
$scope.playingField.data.push([]);
for( var c = 0 ; c < height; c++){
$scope.playingField.data[r].push({ x:c, y:r, alive:false });
}
}
$(".grid").width("600px");
$(".grid").height("600px");
};
Changes color and live status of a cell when clicked on it:
$scope.clickCell = function(cell){ // Zellen Status ändern. tot / leben
cell.alive = !cell.alive;
};
$scope.style = function(value) { // Einen Style zuweisen
return { "background-color": value };
};
This is the part where I think the program gets slowed down. It checks all the cell neighbours and copies a new grid after it; I would be very curious about other solutions to this problem:
$scope.startRound = function(){ // Runde durchlaufen
console.time("Benchmark für das kopieren");
// TODO: Kopieren ist zu langsam, muss anders erfolgen!
var newData = angular.copy($scope.playingField.data);
console.timeEnd("Benchmark für das kopieren");
angular.forEach($scope.playingField.data, function(cells,r){
angular.forEach(cells, function(cell,c){
var alive = 0;
//Nachbarn überprüfen
for(var i = r-1 ; i<=r+1;++i){
for(var j = c-1; j<= c+1 ; ++j){
if($scope.getCell(j,i).alive){
alive++;
}
}
}
if(cell.alive){
alive -=1;
}
// Regeln überprüfen
if(cell.alive == true && (alive < 2 || alive > 3)){
newData[r][c].alive = false;
}
if(cell.alive == true && (alive == 2 || alive == 3)){
newData[r][c].alive = true;
}
if(cell.alive == false && alive == 3){
newData[r][c].alive = true;
}
});
});
$scope.playingField.data = newData;
};
Checks if an alive cell is at the edge of the playing field. If yes, then a new neighbour will be set.
$scope.getCell = function(x,y){ // Nachbarn überprüfen
// Wenn das Spielfeld verlassen wird, wird der Nachbar neu bestimmt (auf der anderen Seite)
var h = $scope.playingField.height-1;
var w = $scope.playingField.width-1;
return $scope.playingField.data[(y+h) % h][(x+w) %w];
};
Functions to start the game, stop the game and to refresh the grid.
$scope.startGame = function(){ // Spiel starten
console.log("Game started");
$scope.stopInterval = $interval($scope.startRound, 10);
};
$scope.stopGame = function(){ // Spiel beenden
console.log("Game stopped");
$interval.cancel($scope.stopInterval);
};
$scope.refreshGameField = function(){ //Sspielfeld zurücksetzen
console.log("Game refreshed");
$scope.createGrid($scope.playingField.width, $scope.playingField.height);
};