Published
Edited
Dec 2, 2018
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
draw = () => {
regen;
ctx.clearRect(0, 0, cwidth, cheight);
ctx.fillStyle = "white";
ctx.fillRect(0, 0, cwidth, cheight);

let columns = cwidth / cell_size;
let rows = cheight / cell_size;

let cstep = cell_size;
let rstep = cell_size;

function getCellIndex(column, row) {
return row * columns + column;
}

function getCellColumnRow(index) {
let column = index % columns;
let row = Math.floor(index / columns);
return [column, row];
}

function expandSquare(cells, covered, index) {
let start = index;
let [scol, srow] = getCellColumnRow(index);
let w = 1;
let h = 1;
function _expand() {
if (w === h) {
let to_expand = [];
let next_column = scol + w;
if (next_column === columns) return [w, h];
for (let i = 0; i < h; i++) {
let eindex = getCellIndex(next_column, srow + i);
let expand_candidate = cells[eindex];
let expand_check =
expand_candidate === null && !covered.includes(eindex);
if (!expand_check) return [w, h];
}
// all expand checks passed
w++;
return _expand();
} else {
let to_expand = [];
let next_row = srow + h;
if (next_row === rows) return [w - 1, h];
for (let i = 0; i < w; i++) {
let eindex = getCellIndex(scol + i, next_row);
let expand_candidate = cells[eindex];
to_expand.push(expand_candidate);
let expand_check =
expand_candidate === null && !covered.includes(eindex);
if (!expand_check) return [w - 1, h];
}
// all expand checks passed
h++;
return _expand();
}
}
return _expand();
}

let cells = [];
for (let r = 0; r < rows; r++) {
for (let c = 0; c < columns; c++) {
cells.push(null);
}
}

let randomly_filled_cells = cells.map(c =>
Math.random() > 0.9 ? "w" : null
);

let expanded = [];
let covered = [];
for (let i = 0; i < cells.length; i++) {
let cell = randomly_filled_cells[i];
if (cell === null && !covered.includes(i)) {
let [col, row] = getCellColumnRow(i);
let [w, h] = expandSquare(randomly_filled_cells, covered, i);
expanded.push([col, row, w, h]);
// add to covered;
for (let r = 0; r < h; r++) {
for (let c = 0; c < w; c++) {
let cindex = getCellIndex(col + c, row + r);
covered.push(cindex);
}
}
}
}

// add obstacles into expanded so we get every cell filled (order does not matter in this case)
// let filled_cells = randomly_filled_cells.filter(c => c === "w").map(c =>;
let filled_converted = [];
for (let i = 0; i < cells.length; i++) {
let cell = randomly_filled_cells[i];
if (cell === "w") {
let [c, r] = getCellColumnRow(i);
filled_converted.push([c, r, 1, 1]);
}
}
let combined = [...expanded, ...filled_converted];

ctx.fillStyle = "black";
for (let cell of combined) {
let [c, r, w, h] = cell;
ctx.beginPath();
ctx.arc(
c * cstep + (w * cstep) / 2,
r * rstep + (h * rstep) / 2,
(w * cstep) / 2- 2,
0,
2 * Math.PI,
false
);
ctx.fill();
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more