[JavaScript] BFS
Format 1\n\nvar minimumMoves = function(grid) {\n    let queue = [{ head: [0, 0], tail: [0, -1], isHorizontal: true }], steps = 0;\n    const visited = new Set(
**Format 1**\n```\nvar minimumMoves = function(grid) {\n    let queue = [{ head: [0, 0], tail: [0, -1], isHorizontal: true }], steps = 0;\n    const visited = new Set(["0,0,0,-1"]);\n    const n = grid.length;\n    const finalPosition = `${n - 1},${n - 1},${n - 1},${n - 2}`;\n    const dirs = [\n        { headMove: [0, 1], tailMove: [0, 1], extraCheckForHead: [] },\n        { headMove: [1, 0], tailMove: [1 ,0], extraCheckForHead: [] },\n        { headMove: [1, -1], tailMove: [0, 0], extraCheckForHead: [[1, 0]], isRotate: true, horizontal: true },\n        { headMove: [-1, 1], tailMove: [0, 0], extraCheckForHead: [[0, 1]], isRotate: true, horizontal: false }\n    ];\n\n    while (queue.length > 0) {\n        const nextPositions = [];\n\n        for (const { head, tail, isHorizontal } of queue) {\n            for (const { headMove, tailMove, extraCheckForHead, isRotate, horizontal } of dirs) {\n                if (horizontal !== undefined && isHorizontal !== horizontal)\n                    continue;\n\n                const nextHeadX = head[0] + headMove[0], nextHeadY = head[1] + headMove[1];\n                const nextTailX = tail[0] + tailMove[0], nextTailY = tail[1] + tailMove[1];\n                const hashCode = `${nextHeadX},${nextHeadY},${nextTailX},${nextTailY}`;\n\n                if (hashCode === finalPosition)\n                    return steps;\n\n                if (\n                    grid[nextHeadX] && grid[nextHeadX][nextHeadY] == 0 &&\n                    grid[nextTailX] && grid[nextTailX][nextTailY] == 0 &&\n                    !visited.has(hashCode) && \n                    extraCheckForHead.every(([xDir, yDir]) =>\n                        grid[xDir + head[0]] && grid[xDir + head[0]][yDir + head[1]] == 0)\n                ) {\n                    nextPositions.push({\n                        head: [nextHeadX, nextHeadY],\n                        tail: [nextTailX, nextTailY],\n                        isHorizontal: isRotate ? !isHorizontal : isHorizontal\n                    })\n                    visited.add(hashCode);                    \n                }\n            }\n        }\n\n        steps++;\n        queue = nextPositions;\n    }\n    \n    return -1;\n};\n```\n**Format 2**\n```\nvar minimumMoves = function(grid) {\n    let queue = [{ tail: [0, 0], isHorizontal: true }], steps = 0;\n    const visited = new Set(["0,0,true"]);\n    const n = grid.length;\n\n    const rotate = (tail, isHorizontal, nextPositions) => {\n        const nextHeadX = isHorizontal ? tail[0] + 1 : tail[0];\n        const nextHeadY = isHorizontal ? tail[1] : tail[1] + 1;\n        const hashCode = `${tail[0]},${tail[1]},${!isHorizontal}`;\n\n        if (\n            grid[tail[0] + 1] && grid[tail[0] + 1][tail[1] + 1] == 0 &&\n            grid[nextHeadX] && grid[nextHeadX][nextHeadY] == 0 &&\n            !visited.has(hashCode)\n        ) {\n            visited.add(hashCode);\n            nextPositions.push({ tail, isHorizontal: !isHorizontal });\n        }\n    };\n    \n    const downMove = (tail, isHorizontal, nextPositions) => {\n        const nextHeadX = isHorizontal ? tail[0] + 1 : tail[0] + 2;\n        const nextHeadY = isHorizontal ? tail[1] + 1 : tail[1];\n        const nextTailX = tail[0] + 1, nextTailY = tail[1];\n        const hashCode = `${nextTailX},${nextTailY},${isHorizontal}`;\n\n        if (\n            grid[nextTailX] && grid[nextTailX][nextTailY] == 0 && \n            grid[nextHeadX] && grid[nextHeadX][nextHeadY] == 0 &&\n            !visited.has(hashCode)\n        ) {\n            visited.add(hashCode);\n            nextPositions.push({ tail: [nextTailX, nextTailY], isHorizontal });\n        }\n    };\n    \n    const rightMove = (tail, isHorizontal, nextPositions) => {\n        const nextHeadX = isHorizontal ? tail[0] : tail[0] + 1;\n        const nextHeadY = isHorizontal ? tail[1] + 2 : tail[1] + 1;\n        const nextTailX = tail[0], nextTailY = tail[1] + 1;\n        const hashCode = `${nextTailX},${nextTailY},${isHorizontal}`;\n\n        if (\n            grid[nextTailX] && grid[nextTailX][nextTailY] == 0 &&\n            grid[nextHeadX] && grid[nextHeadX][nextHeadY] == 0 &&\n            !visited.has(hashCode)\n        ) {\n            visited.add(hashCode);\n            nextPositions.push({ tail: [nextTailX, nextTailY], isHorizontal });\n        }\n    };\n\n    while (queue.length > 0) {\n        const nextPositions = [];\n\n        for (const { tail, isHorizontal } of queue) {\n            if (tail[0] === n - 1 && tail[1] === n - 2)\n                return steps;\n\n            rightMove(tail, isHorizontal, nextPositions), \n            downMove(tail, isHorizontal, nextPositions), \n            rotate(tail, isHorizontal, nextPositions)\n        }\n       \n        steps++;\n        queue = nextPositions;\n    }\n    \n    return -1;\n};\n```
[]