graphics/grid.js

  1. 'use strict';
  2. /**
  3. * @class Grid
  4. * @param {rows} rows - Number of rows in the grid.
  5. * @param {cols} cols - Number of cols in the grid.
  6. */
  7. function Grid(rows, cols) {
  8. if (arguments.length !== 2) {
  9. throw new Error('You should pass exactly 2 arguments to <span ' +
  10. 'class="code">new Grid(rows, cols)</span>');
  11. }
  12. if (typeof rows !== 'number' || !isFinite(rows)) {
  13. throw new TypeError('Invalid value for <span class="code">rows' +
  14. '</span>. Make sure you are passing finite numbers to <span ' +
  15. 'class="code">new Grid(rows, cols)</span>.');
  16. }
  17. if (typeof cols !== 'number' || !isFinite(cols)) {
  18. throw new TypeError('Invalid value for <span class="code">cols' +
  19. '</span>. Make sure you are passing finite numbers to <span ' +
  20. 'class="code">new Grid(rows, cols)</span>.');
  21. }
  22. rows = Math.max(0, rows);
  23. cols = Math.max(0, cols);
  24. this.grid = new Array(rows);
  25. for (var i = 0; i < rows; i++) {
  26. this.grid[i] = new Array(cols);
  27. }
  28. }
  29. /**
  30. * Initializes a Grid from an array.
  31. * @param {array} arr - Array containing elements to be made into a Grid.
  32. */
  33. Grid.prototype.initFromArray = function(arr) {
  34. if (arguments.length !== 1) {
  35. throw new Error('You should pass exactly 1 argument to ' +
  36. '<span class="code">initFromArray</span>');
  37. }
  38. if (!Array.isArray(arr)) {
  39. throw new Error('Invalid value passed to <span class="code">' +
  40. 'initFromArray</span>. Make sure you are passing an array.');
  41. }
  42. for (var i = 0; i < arr.length; i++) {
  43. for (var j = 0; j < arr[0].length; j++) {
  44. if (this.inBounds(i, j)) {
  45. this.set(i, j, arr[i][j]);
  46. }
  47. }
  48. }
  49. };
  50. /**
  51. * Initializes the contents of the grid with `value`.
  52. * @param {number|string|object|boolean} value - The value to be inserted in all
  53. * positions of the grid.
  54. */
  55. Grid.prototype.init = function(value) {
  56. if (arguments.length !== 1) {
  57. throw new Error('You should pass exactly 1 argument to ' +
  58. '<span class="code">init</span>');
  59. }
  60. if (typeof value !== 'boolean' && typeof value !== 'number' &&
  61. typeof value !== 'string' && typeof value !== 'object') {
  62. throw new TypeError('Invalid value passed to <span class="code">' +
  63. 'init</span>. You passed a value of type ' + typeof value +
  64. '. Make sure you are passing a number, string, object, or ' +
  65. 'boolean value.');
  66. }
  67. if (typeof value === 'number' && !isFinite(value)) {
  68. throw new TypeError('Non finite number passed to <span class="code">' +
  69. 'init</span>. If you are passing a number, make sure it is a ' +
  70. 'finite number.');
  71. }
  72. for (var i = 0; i < this.numRows(); i++) {
  73. for (var j = 0; j < this.numCols(); j++) {
  74. this.grid[i][j] = value;
  75. }
  76. }
  77. };
  78. /**
  79. * Gets the object stored at the requested row and column.
  80. * @param {number} row - The row of the desired object.
  81. * @param {number} col - The col of the desired object.
  82. * @returns {number|string|object|boolean} The value stored in the grid
  83. * at that position.
  84. */
  85. Grid.prototype.get = function(row, col) {
  86. if (arguments.length !== 2) {
  87. throw new Error('You should pass exactly 2 arguments to <span ' +
  88. 'class="code">get(row, col)</span>');
  89. }
  90. if (typeof row !== 'number' || !isFinite(row)) {
  91. throw new TypeError('Invalid value for <span class="code">row' +
  92. '</span>. Make sure you are passing finite numbers to <span ' +
  93. 'class="code">get(row, col)</span>.');
  94. }
  95. if (typeof col !== 'number' || !isFinite(col)) {
  96. throw new TypeError('Invalid value for <span class="code">col' +
  97. '</span>. Make sure you are passing finite numbers to <span ' +
  98. 'class="code">get(row, col)</span>.');
  99. }
  100. return this.grid[row][col];
  101. };
  102. /**
  103. * Sets an object at the requested row and column.
  104. * @param {number} row - The row of the destination of the object.
  105. * @param {number} col - The column of the destination of the object.
  106. * @param {number|string|object|boolean} value - The value to be stored at
  107. * the specified location in the grid
  108. */
  109. Grid.prototype.set = function(row, col, value) {
  110. if (arguments.length !== 3) {
  111. throw new Error('You should pass exactly 3 arguments to <span ' +
  112. 'class="code">set(row, col, value)</span>');
  113. }
  114. if (typeof row !== 'number' || !isFinite(row)) {
  115. throw new TypeError('Invalid value for <span class="code">row' +
  116. '</span>. You passed a value of type ' + typeof row +
  117. '. Make sure you are passing a number.');
  118. }
  119. if (typeof col !== 'number' || !isFinite(col)) {
  120. throw new TypeError('Invalid value for <span class="code">col' +
  121. '</span>. You passed a value of type ' + typeof col +
  122. '. Make sure you are passing a number.');
  123. }
  124. if (typeof value !== 'boolean' && typeof value !== 'number' &&
  125. typeof value !== 'string' && typeof value !== 'object') {
  126. throw new TypeError('Invalid value passed to <span class="code">' +
  127. 'set</span>. You passed a value of type ' + typeof value +
  128. '. Make sure you are passing a number, string, object, or ' +
  129. 'boolean value.');
  130. }
  131. if (typeof value === 'number' && !isFinite(value)) {
  132. throw new TypeError('Non finite value passed to <span class="code">' +
  133. 'set</span>. If you are passing a number, make sure it is a ' +
  134. 'finite number.');
  135. }
  136. this.grid[row][col] = value;
  137. };
  138. /**
  139. * Returns the number of rows in the grid.
  140. * @returns {number} The number of rows in the grid.
  141. */
  142. Grid.prototype.numRows = function() {
  143. return this.grid.length;
  144. };
  145. /**
  146. * Returns the number of cols in the grid.
  147. * @returns {number} The number of cols in the grid.
  148. */
  149. Grid.prototype.numCols = function() {
  150. return this.grid[0].length;
  151. };
  152. /**
  153. * Checks whether the given row and col exist in the grid.
  154. * @param {number} row - Row of the position being checked.
  155. * @param {number} col - Col of the position being checked.
  156. * @returns {boolean} Whether or not the given position is in bounds.
  157. */
  158. Grid.prototype.inBounds = function(row, col) {
  159. if (arguments.length !== 2) {
  160. throw new Error('You should pass exactly 2 arguments to <span ' +
  161. 'class="code">inBounds(row, col)</span>');
  162. }
  163. if (typeof row !== 'number' || !isFinite(row)) {
  164. throw new TypeError('Invalid value for <span class="code">row' +
  165. '</span>. Make sure you are passing finite numbers to <span ' +
  166. 'class="code">inBounds(row, col)</span>.');
  167. }
  168. if (typeof col !== 'number' || !isFinite(col)) {
  169. throw new TypeError('Invalid value for <span class="code">col' +
  170. '</span>. Make sure you are passing finite numbers to <span ' +
  171. 'class="code">inBounds(row, col)</span>.');
  172. }
  173. if (row < 0 || col < 0) {
  174. return false;
  175. }
  176. if (row >= this.numRows() || col >= this.numCols()) {
  177. return false;
  178. }
  179. return true;
  180. };
  181. /**
  182. * Converts a grid to a list.
  183. * For example:
  184. * -------
  185. * A B C D
  186. * E F G H
  187. * I J K L
  188. * -------
  189. * would convert to:
  190. * -------
  191. * [[0, 0, 'A'], [0, 1, 'B'], [0, 2, 'C'], [0, 3, 'D'], [1, 0, 'E']...[2, 3, 'L']]
  192. * @returns {array} List representation of the Grid.
  193. */
  194. Grid.prototype.toList = function() {
  195. var list = [];
  196. for (var i = 0; i < this.grid.length; i++) {
  197. for (var j = 0; j < this.grid[0].length; j++) {
  198. var value = this.grid[i][j];
  199. if (value && value !== 0) {
  200. list.push([i, j, value]);
  201. }
  202. }
  203. }
  204. return list;
  205. };
  206. /**
  207. * Generates a string representation of the Grid.
  208. * @returns {string} A representatino of a grid of the format
  209. * "A B C \nD E F \nG H I \n"
  210. */
  211. Grid.prototype.toString = function() {
  212. var result = '';
  213. for (var i = 0; i < this.numRows(); i++) {
  214. for (var j = 0; j < this.numCols(); j++) {
  215. result += this.get(i, j) + ' ';
  216. }
  217. result += '\n';
  218. }
  219. return result;
  220. };
  221. module.exports = Grid;