import 'dart:core'; import 'dart:math'; import 'package:collection/collection.dart'; class Grid extends DelegatingList { final List _internal; final width; final height; Grid(int width, int height) : this._(List(width * height), width, height); Grid.fill(int width, int height, E fillValue) : this._(List.filled(width * height, fillValue), width, height); Grid.from(Grid l) : this._(List.from(l.getRange(0, l.length)), l.width, l.height); Grid.fromList(List l, int width) : this._(l, width, l.length ~/ width); Grid._(l, int w, int h) : _internal = l, width = w, height = h, super(l); /// Return element at coordinate position /// /// Returns the corresponding element after checking the parameters /// for the correct constraints along the width and height of the grid. /// Throws [RangeError] if outside of constraints. Preferred method /// to access elements via coordinates. E get(int x, int y) { int i = toIndex(x, y); if (i >= length || x > width - 1) throw RangeError.index(i, this); return _internal[i]; } /// Sets element at coordinate position /// /// Sets the corresponding element to the [E] parameter [value] passed in. /// Checks against the grid size constraints beforehand and throws /// [RangeError] if outside of constraints. Preferred method to set /// elements via coordinates. void set(int x, int y, E value) { int i = toIndex(x, y); if (i >= length || x > width - 1) throw RangeError.index(i, this); _internal[i] = value; } /// Calculate list index from coordinates /// /// Can be used to get the correct index from coordinates passed in. /// Will only calculate the index, not take into consideration any grid size /// constraints etc; use [get] for that (generally recommended). int toIndex(int x, int y) => (x < 0 || y < 0) ? throw RangeError("Coordinates for Grid Indexing must not be negative.") : y * width + x; /// Calculate coordinates from list index /// /// Calculates the 2-D array coordinates from the corresponding list index /// passed in. Relies on grid width to calculate coordinates. Does not check /// against grid size constraints; use [set] for that (generally recommended). Point toCoordinates(int index) => (index < 0) ? throw RangeError("Index for Grid Coordinates must not be negative") : Point(index % width, index ~/ width); }