[Java 19ms] concise bfs solution with explanation, Please comment if you see things can improve
\nclass Solution {\n    public int minimumMoves(int[][] grid) {\n        if(grid == null || grid.length < 1 || grid[0].length < 2) {\n            return -1;\n  
```\nclass Solution {\n    public int minimumMoves(int[][] grid) {\n        if(grid == null || grid.length < 1 || grid[0].length < 2) {\n            return -1;\n        } \n        \n        int n = grid.length, moves = 0;\n        if(grid[n - 1][n-2] == 1 || grid[n-1][n-1] == 1) {\n            return -1;\n        }\n        \n        boolean[][][] visited = new boolean[n][n][2];                 // location of the tail and two directions\n        Deque<Position> frontier = new LinkedList<Position>(), newFrontier = null;\n        Position target = new Position(n - 1, n - 2, 0), newP = null;\n        frontier.add(new Position(0, 0, 0));\n        visited[0][0][0] = true;\n        while(frontier.size() > 0) {\n           ++moves;\n            newFrontier = new LinkedList<Position>();\n            for(Position cur : frontier) {\n                /// scenairo one moving along the snake\n                int newHeadX = cur.tailX + 2 * dirs[cur.direction][0];\n                int newHeadY = cur.tailY + 2 * dirs[cur.direction][1]; \n                if(newHeadX < n && newHeadY < n && grid[newHeadX][newHeadY] == 0) {\n                    newP = new Position(cur.tailX + dirs[cur.direction][0], cur.tailY + dirs[cur.direction][1], cur.direction);\n                    if(!visited[newP.tailX][newP.tailY][newP.direction]) {\n                        visited[newP.tailX][newP.tailY][newP.direction] = true;\n                        newFrontier.add(newP);\n                    }\n                }\n                \n                // scneario two rotate or moving perpendicular\n                int oDirec = 1 - cur.direction;   // 1 -> 0 or 0 - > 1\n                newHeadX = cur.tailX + dirs[oDirec][0];\n                newHeadY = cur.tailY + dirs[oDirec][1];\n                if(newHeadX < n && newHeadY < n) {\n                    if(grid[newHeadX][newHeadY] == 0\n                       && grid[newHeadX + dirs[cur.direction][0]][newHeadY + dirs[cur.direction][1]] == 0) {\n                        // rotation\n                        newP = new Position(cur.tailX, cur.tailY, oDirec);\n                        if(!visited[newP.tailX][newP.tailY][newP.direction]) {\n                            visited[newP.tailX][newP.tailY][newP.direction] = true;\n                            newFrontier.add(newP);\n                        }\n                        \n                        // moving the entire stack perpendicular to its direction\n                        newP = new Position(newHeadX, newHeadY, cur.direction);\n                        if(!visited[newP.tailX][newP.tailY][newP.direction]) {\n                            visited[newP.tailX][newP.tailY][newP.direction] = true;\n                            newFrontier.add(newP);\n                        }\n                    }\n                }\n            }\n            \n            if(visited[target.tailX][target.tailY][target.direction]) {\n                return moves;    \n            }\n            \n            frontier = newFrontier;\n        }\n        \n        return -1;\n    }\n    \n    private int[][] dirs = new int[][] {{0,1}, {1,0}};\n    public class Position {\n        public int tailX;\n        public int tailY;\n        public int direction;\n        \n        public Position(int x, int y, int direction) {\n            this.tailX = x;\n            this.tailY = y;\n            this.direction = direction;\n        }\n    }\n}\n```
[]