|
<!DOCTYPE html> |
|
<html lang="en"> |
|
|
|
<head> |
|
<style> |
|
:root { |
|
--grid-cols: 150; |
|
--grid-rows: 100; |
|
} |
|
|
|
html, |
|
body { |
|
margin: 0; |
|
padding: 0; |
|
width: 100%; |
|
height: 100%; |
|
} |
|
|
|
.grid { |
|
display: grid; |
|
grid-template-columns: repeat(var(--grid-cols), 1fr); |
|
grid-template-rows: repeat(var(--grid-rows), 1fr); |
|
width: 100%; |
|
height: 100%; |
|
} |
|
|
|
.cell { |
|
outline: 1px solid #eee; |
|
} |
|
|
|
.cell.step { |
|
background-color: #9f9; |
|
} |
|
|
|
.cell.wall { |
|
background-color: #000; |
|
} |
|
|
|
.cell.empty:hover { |
|
outline-color: #f99; |
|
} |
|
</style> |
|
<script src="queue.js"></script> |
|
<script src="grid-to-adjacency-list.js"></script> |
|
<script src="breadth-first.js"></script> |
|
</head> |
|
|
|
<body> |
|
<div id="grid" class="grid"></div> |
|
</body> |
|
<script> |
|
const gridEl = document.querySelector('#grid'); |
|
const gridStyles = window.getComputedStyle(gridEl); |
|
const COLS = parseInt(gridStyles.getPropertyValue('--grid-cols'), 10); |
|
const ROWS = parseInt(gridStyles.getPropertyValue('--grid-rows'), 10); |
|
const ids = {}; |
|
const cells = []; |
|
|
|
const showPath = () => { |
|
// FIXME we may update only adjacent cells instead of rebuilding whole list |
|
const adjList = gridToAdjacencyList(cells, COLS); |
|
|
|
breathFirstSearch(adjList, cells).forEach((index) => { |
|
const cell = cells[index]; |
|
|
|
cell.classList.remove('empty'); |
|
cell.classList.add('step'); |
|
}); |
|
}; |
|
|
|
const cellOnClick = ({ target }) => { |
|
document.querySelectorAll('.cell.step').forEach((el) => { |
|
el.classList.remove('step'); |
|
el.classList.add('empty'); |
|
}); |
|
|
|
if (target.classList.contains('wall')) { |
|
target.type = 'empty'; |
|
target.classList.remove('wall'); |
|
target.classList.add('empty'); |
|
} else { |
|
target.type = 'wall'; |
|
target.classList.remove('empty'); |
|
target.classList.add('wall'); |
|
} |
|
|
|
showPath(); |
|
}; |
|
|
|
const getCellId = (row, col) => `cell-${row}-${col}`; |
|
const { getIndex, getCell, isEmpty } = generateFns(COLS); |
|
const count = COLS * ROWS; |
|
for (let i = 0; i < count; i++) { |
|
const row = Math.floor(i / COLS); |
|
const col = i % COLS; |
|
const el = document.createElement('div'); |
|
const id = getCellId(row, col); |
|
const type = Math.random() < 0.3 ? 'wall' : 'empty'; |
|
Object.assign(el, { id, index: i, row, col, type }); |
|
el.addEventListener('click', cellOnClick); |
|
el.className = `cell ${type}`; |
|
ids[id] = el; |
|
cells[i] = el; |
|
} |
|
grid.append(...cells); |
|
|
|
showPath(); |
|
</script> |
|
|
|
</html> |