
本文介绍一种基于贪心策略的网格着色算法,通过动态筛选可用颜色并实时校验上下左右邻格,确保生成的二维布局满足“无相邻同色”约束,同时兼顾分布随机性与可行性判断。
本文介绍一种基于贪心策略的网格着色算法,通过动态筛选可用颜色并实时校验上下左右邻格,确保生成的二维布局满足“无相邻同色”约束,同时兼顾分布随机性与可行性判断。
在构建如“题册分发网格”这类可视化应用时,仅对颜色数组全局随机打乱(shuffle)无法保证空间局部约束——即任意两个上下或左右相邻的单元格不能使用相同颜色。原始实现直接 pop() 颜色导致布局完全忽略邻域状态,极易出现连续同色块。要真正解决该问题,需将着色过程从“事后分配”转变为“事前验证”,即:每填入一个单元格前,动态计算其当前可选颜色集合,并从中随机选取。
核心思路:逐格约束驱动填充
我们采用行优先遍历(row-major order),对每个位置 (row, col) 执行以下步骤:
javascript实现购物车效果,通过原生js代码实现购物车效果,一般电商网站或者商城网站会使用到购物车的效果,点击加减,总价随之变化,选中商品,点击删除,可以删除选中的商品!
- 识别已着色的邻格:仅需检查左侧单元格(同一行,列-1)和上方单元格(上一行,同列),因为按顺序填充时,右侧与下方单元格尚未着色;
- 构建可用颜色池:从剩余颜色列表中过滤掉与左/上邻格相同的颜色;
- 可行性判定:若可用颜色为空,则立即终止并提示“无法满足无相邻同色约束”;
- 随机选取并消耗:从可用池中随机选一颜色,赋值给当前单元格,并从全局剩余颜色数组中移除该颜色。
✅ 优势:时间复杂度可控(O(R×C×K),K为颜色种类数),逻辑清晰,易于调试;
⚠️ 注意:该策略不保证全局最优解(如回溯法),但对多数实际场景(如4色、中等规模网格)具备高成功率。
关键代码实现(含完整逻辑)
function distributeBooks() {
const rows = parseInt(document.getElementById("rows").value) || 0;
const cols = parseInt(document.getElementById("cols").value) || 0;
const whiteCount = parseInt(document.getElementById("whiteCount").value) || 0;
const pinkCount = parseInt(document.getElementById("pinkCount").value) || 0;
const greenCount = parseInt(document.getElementById("greenCount").value) || 0;
const yellowCount = parseInt(document.getElementById("yellowCount").value) || 0;
const totalCells = rows * cols;
const colors = [
...Array(whiteCount).fill("white"),
...Array(pinkCount).fill("pink"),
...Array(greenCount).fill("green"),
...Array(yellowCount).fill("yellow")
];
if (colors.length 0 ? tr.children[col - 1].className : null;
const topColor = row > 0
? table.children[row - 1].children[col].className
: null;
// 构建当前可选颜色:排除左、上邻色
const availableColors = colors.filter(
color => color !== leftColor && color !== topColor
);
// 检查是否仍有可行选择
if (availableColors.length === 0) {
alert("无法满足无相邻同色约束,请调整各颜色数量或网格尺寸。");
return;
}
// 随机选取一个可用颜色
const randomIndex = Math.floor(Math.random() * availableColors.length);
const selectedColor = availableColors[randomIndex];
td.className = selectedColor;
// 从总池中移除已用颜色(关键!)
const idx = colors.indexOf(selectedColor);
colors.splice(idx, 1);
tr.appendChild(td);
}
table.appendChild(tr);
}
}
进阶建议与注意事项
- 颜色数量均衡性:若某颜色占比过高(如 >50%),即使总数量足够,也极易触发 availableColors.length === 0。建议各颜色数量尽量接近 totalCells / colorCount;
- 增强随机性:可在每次筛选 availableColors 后,对其执行一次局部 shuffle(如使用 Fisher-Yates),避免固定顺序偏好;
- 扩展方向:如需支持四邻域(含对角线)约束,需额外检查左上、右上单元格,但会显著增加冲突概率,此时建议引入回溯或图着色算法(如 Welsh-Powell);
- 性能优化:对超大网格(如 >100×100),可预统计各颜色剩余数量,用 Map 替代 indexOf 和 splice,提升查找与删除效率。
该方案已在 JSFiddle 示例 中验证有效,兼顾实用性与教学性,是解决此类约束布局问题的稳健起点。










