Java easy-readable BFS solution
It\'s common to use BFS to find a shortest path, the difference is the rule of how to expand each step to a new one.\n```\npublic int minimumMoves(int[][] grid)
It\'s common to use BFS to find a shortest path, the difference is the rule of how to expand each step to a new one.\n```\npublic int minimumMoves(int[][] grid) {\n        int n = grid.length;\n        if (grid[n - 1][n - 2] != 0 || grid[n - 1][n - 1] != 0) {\n            return -1;\n        }\n        int step = 0;\n        int[] start = new int[]{0, 0, 0, 1};\n        Queue<int[]> q = new LinkedList<>();\n        q.offer(start);\n        Set<String> visited = new HashSet<>();\n        visited.add(pos2Str(start));\n\n        while (!q.isEmpty()) {\n            for (int cnt = q.size(); cnt > 0; cnt--) {\n                int[] cur = q.poll();\n                if (cur[0] == n - 1 && cur[1] == n - 2 && cur[2] == n - 1 && cur[3] == n - 1) {\n                    return step;\n                }\n                // expand\n                List<int[]> nextList = expand(grid, cur);\n                for (int[] next : nextList) {\n                    String posStr = pos2Str(next);\n                    if (!visited.contains(posStr)) {\n                        visited.add(posStr);\n                        q.offer(next);\n                    }\n                }\n            }\n            step++;\n        }\n        return -1;\n    }\n\n    private List<int[]> expand(int[][] grid, int[] cur) {\n        List<int[]> result = new ArrayList<>();\n        int n = grid.length;\n\n        int[] next;\n        if (cur[0] == cur[2]) {  // cur horizon\n            // right\n            if (cur[3] + 1 < n && grid[cur[0]][cur[3] + 1] == 0) {\n                next = new int[]{cur[0], cur[1] + 1, cur[0], cur[3] + 1};\n                result.add(next);\n            }\n\n            if (cur[0] + 1 < n && grid[cur[0] + 1][cur[1]] == 0 && grid[cur[0] + 1][cur[3]] == 0) {\n                // down\n                next = new int[]{cur[0] + 1, cur[1], cur[0] + 1, cur[3]};\n                result.add(next);\n                // clock wise\n                next = new int[]{cur[0], cur[1], cur[0] + 1, cur[1]};\n                result.add(next);\n            }\n        } else { // vertical\n            if (cur[1] + 1 < n && grid[cur[0]][cur[1] + 1] == 0 && grid[cur[2]][cur[1] + 1] == 0) {\n                // right\n                next = new int[]{cur[0], cur[1] + 1, cur[2], cur[1] + 1};\n                result.add(next);\n                //counterclockwise\n                next = new int[]{cur[0], cur[1], cur[0], cur[1] + 1};\n                result.add(next);\n            }\n            // down\n            if (cur[2] + 1 < n && grid[cur[2] + 1][cur[1]] == 0) {\n                next = new int[]{cur[0] + 1, cur[1], cur[2] + 1, cur[1]};\n                result.add(next);\n            }\n        }\n        return result;\n    }\n\n    private String pos2Str(int[] pos) {\n        StringBuilder sb = new StringBuilder();\n        for (int i = 0; i < pos.length; i++) {\n            sb.append(pos[i]);\n            sb.append(\'@\');\n        }\n        return sb.toString();\n    }
[]