Java - BFS easy to understand
\nclass Solution {\n    int n;\n    public int minimumMoves(int[][] grid) {\n        n = grid.length; \n        boolean[][][] visited = new boolean[n][n][2];//[
```\nclass Solution {\n    int n;\n    public int minimumMoves(int[][] grid) {\n        n = grid.length; \n        boolean[][][] visited = new boolean[n][n][2];//[x][y][0]: right, [x][y][1] : down\n        Queue<int[]> queue = new LinkedList<>();\n        queue.add(new int[]{0,0,0,1});\n        visited[0][0][0] = true;\n        int moves = 0;\n        while(!queue.isEmpty()) {\n            int size = queue.size();\n            while(size -- > 0) {\n                int[] cur = queue.poll();\n                if (cur[0] == n - 1 && cur[1] == n - 2 && cur[2] == n - 1 && cur[3] == n - 1) {\n                    return moves;\n                }\n                //next moves\n                // rule move #1\n                int a = cur[0], b = cur[1] + 1, c = cur[2], d = cur[3] + 1;\n                if (isValid(a, b) && grid[a][b] == 0 && isValid(c,d) && grid[c][d] == 0) {\n                    if (a == c) {// horizontial\n                        if (!visited[a][b][0]) {\n                            queue.add(new int[]{a, b, c, d});\n                            visited[a][b][0] = true;\n                        }\n                    } else { // vertial\n                        if (!visited[a][b][1]) {\n                            queue.add(new int[]{a, b, c, d});\n                            visited[a][b][1] = true;\n                        }\n                    }\n                }\n                // rule move #2\n                a = cur[0] + 1; b = cur[1]; c = cur[2] + 1; d = cur[3];\n                if (isValid(a, b) && grid[a][b] == 0 && isValid(c,d) && grid[c][d] == 0) {\n                    if (a == c) {// horizontial\n                        if (!visited[a][b][0]) {\n                            queue.add(new int[]{a, b, c, d});\n                            visited[a][b][0] = true;\n                        }\n                    } else { // vertial\n                        if (!visited[a][b][1]) {\n                            queue.add(new int[]{a, b, c, d});\n                            visited[a][b][1] = true;\n                        }\n                    }\n                }\n                // rule move #3\n                if (cur[0] == cur[2]) { // horizontial\n                    if (isValid(cur[0] + 1, cur[1]) && isValid(cur[2] + 1, cur[3]) && grid[cur[0] + 1][cur[1]] == 0 && grid[cur[2] + 1][cur[3]] == 0) {\n                        a = cur[0]; b = cur[1]; c = cur[0] + 1; d = cur[1];\n                        if (!visited[a][b][1]) {\n                            queue.add(new int[]{a, b, c, d});\n                            visited[a][b][0] = true;\n                        }\n                    }\n                } else { // vertial\n                    if (isValid(cur[0], cur[1] + 1) && isValid(cur[2], cur[3] + 1) && grid[cur[0]][cur[1] + 1] == 0 && grid[cur[2]][cur[3] + 1] == 0) {\n                        a = cur[0]; b = cur[1]; c = cur[0]; d = cur[1] + 1;\n                        if (!visited[a][b][0]) {\n                            queue.add(new int[]{a, b, c, d});\n                            visited[a][b][0] = true;\n                        }\n                    }\n                }\n            }\n            \n            moves ++;\n        }\n        \n        return -1;\n    }\n    \n    boolean isValid(int x, int y) {\n        if (x >= 0 && x < n && y >= 0 && y < n) {\n            return true;\n        }\n        \n        return false;\n    }\n}\n```
[]