You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 00:40:42