| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 | function Grid(size, previousState) {  this.size = size;  this.cells = previousState ? this.fromState(previousState) : this.empty();}// Build a grid of the specified sizeGrid.prototype.empty = function () {  var cells = [];  for (var x = 0; x < this.size; x++) {    var row = cells[x] = [];    for (var y = 0; y < this.size; y++) {      row.push(null);    }  }  return cells;};Grid.prototype.fromState = function (state) {  var cells = [];  for (var x = 0; x < this.size; x++) {    var row = cells[x] = [];    for (var y = 0; y < this.size; y++) {      var tile = state[x][y];      row.push(tile ? new Tile(tile.position, tile.value) : null);    }  }  return cells;};// Find the first available random positionGrid.prototype.randomAvailableCell = function () {  var cells = this.availableCells();  if (cells.length) {    return cells[Math.floor(Math.random() * cells.length)];  }};Grid.prototype.availableCells = function () {  var cells = [];  this.eachCell(function (x, y, tile) {    if (!tile) {      cells.push({ x: x, y: y });    }  });  return cells;};// Call callback for every cellGrid.prototype.eachCell = function (callback) {  for (var x = 0; x < this.size; x++) {    for (var y = 0; y < this.size; y++) {      callback(x, y, this.cells[x][y]);    }  }};// Check if there are any cells availableGrid.prototype.cellsAvailable = function () {  return !!this.availableCells().length;};// Check if the specified cell is takenGrid.prototype.cellAvailable = function (cell) {  return !this.cellOccupied(cell);};Grid.prototype.cellOccupied = function (cell) {  return !!this.cellContent(cell);};Grid.prototype.cellContent = function (cell) {  if (this.withinBounds(cell)) {    return this.cells[cell.x][cell.y];  } else {    return null;  }};// Inserts a tile at its positionGrid.prototype.insertTile = function (tile) {  this.cells[tile.x][tile.y] = tile;};Grid.prototype.removeTile = function (tile) {  this.cells[tile.x][tile.y] = null;};Grid.prototype.withinBounds = function (position) {  return position.x >= 0 && position.x < this.size &&         position.y >= 0 && position.y < this.size;};Grid.prototype.serialize = function () {  var cellState = [];  for (var x = 0; x < this.size; x++) {    var row = cellState[x] = [];    for (var y = 0; y < this.size; y++) {      row.push(this.cells[x][y] ? this.cells[x][y].serialize() : null);    }  }  return {    size: this.size,    cells: cellState  };};
 |