JS拼图:如何判断方块可移动并与空白方块交换
方块移动与空白方块交换的实现问题
我想要实现点击方块时,将它和空白方块(编号9的方块)交换位置,但交换前必须验证该方块是否可移动。我对这部分逻辑的实现感到困惑,看了很多方案还是没理解,而且有些方案用了jQuery,我也没掌握。以下是我的尝试代码:
randomOrder.forEach((el, i) => { const block = document.createElement('div') block.classList.add('block') block.id = "b" + el block.style.left = (4 + 98 * (i % 3)) + 'px' block.style.top = (4 + 98 * Math.floor(i / 3)) + 'px' block.innerText = el == 9 ? "" : el if(el == 9){ freeBlock = block } container.appendChild(block) }) // 获取点击的方块 container.addEventListener("click", (e) => { var clickedBlock = e.target if (e.target.id === "b9") { return } else { moveBlock(clickedBlock) } }) // 移动方块的函数 function moveBlock(clickedBlock) { // 移动前先检查是否可移动 if (isMovable(clickedBlock)) { console.log(clickedBlock.offsetLeft) } } // 结束moveBlock() // 检查方块是否可移动 function isMovable(clickedBlock) { if(clickedBlock.offsetLeft === freeBlock.offsetLeft){ if(clickedBlock.offsetTop === freeBlock.offsetTop){ return true } } } // 结束可移动检查
问题修正与实现方案
1. 修复isMovable函数的判断逻辑
当前的isMovable函数逻辑完全错误——它仅在点击方块与空白方块完全重合时返回true,这不符合可移动的实际要求。可移动的方块需满足:与空白方块在同一行/列,且位置相邻。
修改后的函数:
function isMovable(clickedBlock) { // 计算水平、垂直方向的距离差(取绝对值避免正负问题) const leftDiff = Math.abs(clickedBlock.offsetLeft - freeBlock.offsetLeft); const topDiff = Math.abs(clickedBlock.offsetTop - freeBlock.offsetTop); // 可移动条件:同一列且垂直间距为98px,或同一行且水平间距为98px return (leftDiff === 0 && topDiff === 98) || (topDiff === 0 && leftDiff === 98); }
2. 实现方块交换逻辑
验证通过后,需要交换两个方块的位置、ID、文本内容,并更新freeBlock的指向,保证后续判断准确:
function moveBlock(clickedBlock) { if (isMovable(clickedBlock)) { // 交换位置样式 const tempLeft = clickedBlock.style.left; const tempTop = clickedBlock.style.top; clickedBlock.style.left = freeBlock.style.left; clickedBlock.style.top = freeBlock.style.top; freeBlock.style.left = tempLeft; freeBlock.style.top = tempTop; // 交换ID const tempId = clickedBlock.id; clickedBlock.id = freeBlock.id; freeBlock.id = tempId; // 交换文本内容 const tempText = clickedBlock.innerText; clickedBlock.innerText = freeBlock.innerText; freeBlock.innerText = tempText; // 更新空白方块的引用 freeBlock = clickedBlock; } }
3. 关键说明
- 方块间距(98px)需与初始化时的计算保持一致,否则相邻判断会失效。
- 交换时必须同步更新所有关联属性(位置、ID、文本、
freeBlock引用),否则后续移动逻辑会出现错误。
内容的提问来源于stack exchange,提问作者Rawley
相关产品推荐
相关产品推荐

