[Java] BFS Solution - Very clean code easy to understand
java\npublic class Solution {\n    public int minimumMoves(int[][] grid) {\n        int n = grid.length;\n        SnakePos src = new SnakePos(new Cell(0, 0), ne
```java\npublic class Solution {\n    public int minimumMoves(int[][] grid) {\n        int n = grid.length;\n        SnakePos src = new SnakePos(new Cell(0, 0), new Cell(0, 1));\n        SnakePos dst = new SnakePos(new Cell(n - 1, n - 2), new Cell(n - 1, n - 1));\n\n        HashSet<String> visited = new HashSet<>();\n        Queue<SnakePos> queue = new LinkedList<>();\n        queue.add(src);\n        visited.add(src.getKey());\n\n        ArrayList<SnakePos> nextMoves = new ArrayList<>(4);\n        int steps = 0;\n        while (!queue.isEmpty()) {\n            int size = queue.size();\n            for (int i = 0; i < size; i++) {\n                SnakePos top = queue.remove();\n                if (top.equals(dst))\n                    return steps;\n\n                nextMoves.clear();\n                nextMoves.add(tryMoveRight(top, grid));\n                nextMoves.add(tryMoveDown(top, grid));\n                nextMoves.add(tryMoveClockwise(top, grid));\n                nextMoves.add(tryMoveCounterClockwise(top, grid));\n\n                for (SnakePos next : nextMoves) {\n                    if (next != null && !visited.contains(next.getKey())) {\n                        visited.add(next.getKey());\n                        queue.add(next);\n                    }\n                }\n            }\n            steps++;\n        }\n\n        return -1;\n    }\n\n    SnakePos tryMoveRight(SnakePos curr, int[][] grid) {\n        SnakePos next = new SnakePos(\n                new Cell(curr.cell1.r, curr.cell1.c + 1),\n                new Cell(curr.cell2.r, curr.cell2.c + 1)\n        );\n        if (valid(next, grid))\n            return next;\n        return null;\n    }\n\n    SnakePos tryMoveDown(SnakePos curr, int[][] grid) {\n        SnakePos next = new SnakePos(\n                new Cell(curr.cell1.r + 1, curr.cell1.c),\n                new Cell(curr.cell2.r + 1, curr.cell2.c)\n        );\n        if (valid(next, grid))\n            return next;\n        return null;\n    }\n\n    SnakePos tryMoveClockwise(SnakePos curr, int[][] grid) {\n        if (curr.cell1.r == curr.cell2.r) {\n            SnakePos next = new SnakePos(\n                    new Cell(curr.cell1.r, curr.cell1.c),\n                    new Cell(curr.cell2.r + 1, curr.cell2.c - 1)\n            );\n            if (valid(next.cell2, grid)\n                    && valid(new Cell(curr.cell1.r + 1, curr.cell1.c + 1), grid)) {\n                return next;\n            }\n        }\n        return null;\n    }\n\n    SnakePos tryMoveCounterClockwise(SnakePos curr, int[][] grid) {\n        if (curr.cell1.c == curr.cell2.c) {\n            SnakePos next = new SnakePos(\n                    new Cell(curr.cell1.r, curr.cell1.c),\n                    new Cell(curr.cell2.r - 1, curr.cell2.c + 1)\n            );\n            if (valid(next.cell2, grid)\n                    && valid(new Cell(curr.cell1.r + 1, curr.cell1.c + 1), grid)) {\n                return next;\n            }\n        }\n        return null;\n    }\n\n    boolean valid(int r, int c, int[][] grid) {\n        int n = grid.length;\n        return r >= 0 && r < n && c >= 0 && c < n && grid[r][c] == 0;\n    }\n\n    boolean valid(Cell cell, int[][] grid) {\n        return valid(cell.r, cell.c, grid);\n    }\n\n    boolean valid(SnakePos snakePos, int[][] grid) {\n        return valid(snakePos.cell1, grid) && valid(snakePos.cell2, grid);\n    }\n\n    // For testing and debug on IDE purpose\n    public static void main(String[] args) {\n        int[][] grid = {\n                {0, 0, 0, 0, 0, 1},\n                {1, 1, 0, 0, 1, 0},\n                {0, 0, 0, 0, 1, 1},\n                {0, 0, 1, 0, 1, 0},\n                {0, 1, 1, 0, 0, 0},\n                {0, 1, 1, 0, 0, 0}\n        };\n\n        Solution sol = new Solution();\n        System.out.println(sol.minimumMoves(grid));\n    }\n}\n\nclass Cell {\n    int r, c;\n\n    public Cell(int r, int c) {\n        this.r = r;\n        this.c = c;\n    }\n\n    public String getKey() {\n        return r + "," + c;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        Cell cell = (Cell) obj;\n        return r == cell.r && c == cell.c;\n    }\n}\n\nclass SnakePos {\n    Cell cell1, cell2;\n\n    public SnakePos(Cell cell1, Cell cell2) {\n        this.cell1 = cell1;\n        this.cell2 = cell2;\n    }\n\n    public String getKey() {\n        return cell1.getKey() + ":" + cell2.getKey();\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        SnakePos snakePos = (SnakePos) obj;\n        return snakePos.cell1.equals(cell1) && snakePos.cell2.equals(cell2);\n    }\n}\n```
['Breadth-First Search', 'Java']