Как можно сравнить цвет в матрице?
Я создал матрицу размером 5 на 5 со случайными цветами, но не могу понять как сравнить близ стоящие клетки во время отрисовки матрицы, а также при нажатии на клетку, чтобы цвета не сливались. То есть слева, справа, сверху и снизу цвета не должны повторяться. При этом нужно использовать чистый JS. Вот мой код:
const MATRIX_SIZE = 5;
const ELEMENT_SIZE = 40;
const rootNode = document.getElementById("app");
const getRandomColor = () => {
const colors = [
"black",
"blue",
"red",
"magenta",
"green",
"cyan",
"yellow",
"white"
];
return colors[Math.floor(Math.random() * colors.length)];
};
const usedColors = Array.from({
length: MATRIX_SIZE
}, (_, i) => []);
const getNextColor = (useColors, row, col) => {
let nextColor = getRandomColor();
let prevColor;
while (
(useColors[row - 1] || [])[col] === nextColor ||
(useColors[row + 1] || [])[col] === nextColor ||
useColors[row][col - 1] === nextColor ||
useColors[row][col + 1] === nextColor ||
useColors[row][col] === nextColor ||
prevColor === nextColor
) {
prevColor = nextColor;
nextColor = getRandomColor();
}
useColors[row].length < MATRIX_SIZE ?
useColors[row].push(nextColor) :
(useColors[row][col] = nextColor);
return nextColor;
};
for (let row = 0; row < MATRIX_SIZE; row++) {
for (let col = 0; col < MATRIX_SIZE; col++) {
const square = document.createElement("div");
square.style.cssText = `
position: absolute;
width: ${ELEMENT_SIZE}px;
height: ${ELEMENT_SIZE}px;
left: ${ELEMENT_SIZE * col}px;
top: ${ELEMENT_SIZE * row}px;
background-color: ${getNextColor(usedColors, row, col)}
`;
square.setAttribute("data-row", row);
square.setAttribute("data-col", col);
rootNode.append(square);
}
}
document.addEventListener("click", (evt) => {
const square = evt.target.closest("[data-row]");
if (square) {
const {
row,
col
} = square.dataset;
square.style.backgroundColor = getNextColor(usedColors, row, col);
}
});
<!DOCTYPE html>
<html>
<head>
<title>color matrix</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="app"></div>
<script src="src/index.js">
</script>
</body>
</html>
UPD:
Получилось сгенерировать матрицу где рядом стоящие цвета отличаются, но при клике, цвета с ячейками справа и снизу от той которую нажал иногда совпадают. Код подправил
Ответы (1 шт):
Автор решения: EzioMercer
→ Ссылка
Предлагаю такой алгоритм:
let matrixCount = 0;
const colors = [
'black',
'blue',
'red',
'magenta',
'green',
'cyan',
'yellow',
'white'
];
const getRandColor = () => colors[Math.floor(Math.random() * colors.length)];
const getColorForCell = (rowNum, cellNum, matrix, currentColor) => {
const nearestCellsBgColors = new Set([
matrix?.[rowNum]?.[cellNum - 1],
matrix?.[rowNum]?.[cellNum + 1],
matrix?.[rowNum - 1]?.[cellNum],
matrix?.[rowNum + 1]?.[cellNum]
].map(nearestCell => nearestCell?.style.backgroundColor || ''));
nearestCellsBgColors.add(currentColor);
while (true) {
const bgColor = getRandColor();
if (nearestCellsBgColors.has(bgColor)) continue;
return bgColor;
};
}
const createCellDiv = (rowNum, cellNum, matrix, matrixId) => {
const cellDiv = document.createElement('div');
const id = matrixId + '-' + rowNum + '-' + cellNum;
cellDiv.className = 'cell cell-' + id;
cellDiv.id = 'cell-' + id;
cellDiv.style.backgroundColor = getColorForCell(rowNum, cellNum, matrix, '');
cellDiv.addEventListener('click', () => {
cellDiv.style.backgroundColor = getColorForCell(rowNum, cellNum, matrix, cellDiv.style.backgroundColor);
});
return cellDiv;
}
const createRowDiv = (rowNum, cellsNum, matrix, matrixId) => {
const row = [];
matrix.push(row);
const rowDiv = document.createElement('div');
const id = matrixId + '-' + rowNum;
rowDiv.className = 'row row-' + id;
rowDiv.id = 'row-' + id;
for (let cellNum = 0; cellNum < cellsNum; ++cellNum) {
const cell = createCellDiv(rowNum, cellNum, matrix, matrixCount);
row.push(cell);
rowDiv.appendChild(cell);
}
return rowDiv;
}
const createMatrix = (rowsNum, cellsNum, appendTo) => {
const matrix = [];
const matrixDiv = document.createElement('div');
const matrixId = matrixCount;
matrixDiv.className = 'matrix matrix-' + matrixId;
matrixDiv.id = 'matrix-' + matrixId;
for (let rowNum = 0; rowNum < rowsNum; ++rowNum) {
const rowDiv = createRowDiv(rowNum, cellsNum, matrix, matrixId);
matrixDiv.appendChild(rowDiv);
}
document.querySelector(appendTo).appendChild(matrixDiv);
++matrixCount;
return {
matrix,
matrixDiv
};
}
createMatrix(4, 8, '#app1');
createMatrix(4, 12, '#app2');
body {
background-color: gray;
}
.row {
display: flex;
width: max-content;
}
.cell {
width: 50px;
height: 50px;
}
<div id="app1"></div>
<br/>
<div id="app2"></div>