Monday, February 28, 2011

HW6 Graded and my Solution

I have just emailed the grades for HW 6. People seem to be having trouble with creating closures. Below is my solution to the this homework. Notice how the makeDisperse function creates other functions (closures), each of which with possibly different 'neighbors' depending on the arguments passed to makeDisperse.

//Returns a list of the 4 elements that are North, South, East and West of the 
// button with id= 'b' + row + col
function getNeighbors (row, col) {
 var result = [];
 var nrow = (row == 0) ? SIZE - 1 : row - 1;
 var ncol = col;
 result.push(document.getElementById('b'+ nrow + ncol));
 nrow = row
 ncol = (col + 1) % SIZE;
 result.push(document.getElementById('b' + nrow + ncol));
 nrow = (row + 1) % SIZE;
 ncol = col;
 result.push(document.getElementById('b' + nrow + ncol));
 nrow = row;
 ncol = (col == 0) ? SIZE - 1 : col -1;
 result.push(document.getElementById('b' + nrow + ncol));
 return result;
}


//Creates and returns an event handler which is a closure that holds
// 'neighbors', a list of the 4 elements that are North, S, E, West of the
// button at row,col. The function it returns distributes the value of this
// over the 4 neighbors.
function makeDisperse(row, col){
 var neighbors = getNeighbors(row,col);
 function disperse () {
  var myNumber = Number(this.value);
  while (myNumber > 0){
    for (var i =0; i < neighbors.length; i++){
     var nelement = neighbors[i];
     nelement.value = Number(nelement.value) + 1;
     myNumber--;
     if (myNumber <= 0 ) { break;}
    }
  }
  this.value = 0;
  updateScore();
 };
 return disperse;
}

//This method on <body onload="setup()". It sets an event-handler for every button.
function setup(){
 for (var row =0; row < SIZE; row++){
  for (var col=0; col < SIZE; col++){
   var button = document.getElementById('b' + row + col);
   button.onclick = makeDisperse(row,col);
  }
 }
}


//Updates the value of the score button to be the count of all the zeros in all the buttons.
function updateScore(){
 var total = 0;
 for (var row =0; row < SIZE; row++){
  for (var col=0; col < SIZE; col++){
   var button = document.getElementById('b' + row + col);
   if ('0' == button.value) {
    total++;
   }
  }
 }
 var scoreButton = document.getElementById('score');
 score.value = total;
}

People do a lot of JavaScript programming without understanding closures. Still, they are a really useful and powerful feature of the language: used for creating private variables, custom functions (as above), and namespaces, among other uses. I think you will be a much better developer if you understand and use them as needed.

No comments:

Post a Comment