Java Organized BFS Solution (Beats 100% both Time and Space Complexity)
Create a class to represent the Position of the snake and the number of moves it took to reach that Position.\n\nTraverse BFS to traverse the closest positions 
Create a class to represent the Position of the snake and the number of moves it took to reach that Position.\n\nTraverse BFS to traverse the closest positions FIRST, and saving the already traversed Positions in a Visited Set to avoid traversing them again. This works because the first traversal of a Position WILL be the SHORTEST since we\'re using BFS.\n\nFor each iteration, check to see if position has reached the target, if true, then return the saved number of Moves. No need to explore more paths since with the given number of moves (Right, Down, CounterClockwise, Clockwise) with no repeated positions allowed, if the snake reaches the end, it will always be in the same number of moves.\nE.g: If the Snake reaches the end in 11 moves, it won\'t be able to reach the end in more or less moves if another solution exists.\n\n```\nclass Position {\n    int x1 = 0;\n    int y1 = 0;\n    int x2 = 0;\n    int y2 = 0;\n    int moves;\n    // (x1, y1) is front\n    // (x2, y2) is behind\n    public Position(int x1, int y1, int x2, int y2) {\n        this.x1 = x1;\n        this.x2 = x2;\n        this.y1 = y1;\n        this.y2 = y2;\n        this.moves = 0;\n    }\n    \n    public Position(int x1, int y1, int x2, int y2, int moves) {\n        this.x1 = x1;\n        this.x2 = x2;\n        this.y1 = y1;\n        this.y2 = y2;\n        this.moves = moves;\n    }\n    \n    // Used to compare Positions within Set to avoid duplicates\n    @Override \n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null) return false;\n        if (!(o instanceof Position)) {\n            return false;\n        }\n        Position p = (Position) o;\n        return (p.x1 == this.x1 && p.y1 == this.y1\n           && p.x2 == this.x2 && p.y2 == this.y2);\n    }\n    @Override\n    public int hashCode() {\n        int result = 17;\n        result = 31 * result + this.x1;\n        result = 31 * result + this.x2;\n        result = 31 * result + this.y1;\n        result = 31 * result + this.y2;\n        return result;\n        \n    }\n}\npublic class Solution {\n    private int n;\n    private Set<Position> visited;\n    public int minimumMoves(int[][] grid) {\n        if (grid == null || grid.length == 0 || grid[0].length == 0) return -1;\n        \n        // Initializing variables, setup \n        n = grid.length;\n        visited = new HashSet<Position>();\n        Position position = new Position(0, 1, 0, 0);\n        Queue<Position> q = new LinkedList<>();\n        \n        q.offer(position);\n        if (!validateValidP(grid, position)) {\n            return -1;\n        }\n        \n        // BFS\n        while (!q.isEmpty()) {\n            Position cur = q.poll();\n            Position right = moveRight(grid, cur, cur.moves);\n            Position down = moveDown(grid, cur, cur.moves);\n            Position clock = moveClock(grid, cur, cur.moves);\n            Position counterClock = moveCounterClock(grid, cur, cur.moves);\n            if (validateWin(cur)) {\n                return cur.moves;\n            }\n            if (right != null) {\n                q.offer(right);\n            }\n            if (down != null) {\n                q.offer(down);\n            }\n            if (clock != null) {\n                q.offer(clock);\n            }\n            if (counterClock != null) {\n                q.offer(counterClock);\n            }\n        }\n        return -1;\n        \n    }\n    private Position moveRight(int[][] grid, Position p, int moves) {\n        Position rightP = new Position(p.x1, p.y1 + 1, p.x2, p.y2 + 1, moves + 1);\n        if (validateValidP(grid, rightP)) {\n            return rightP;\n        }\n        return null;\n    }\n    private Position moveDown(int[][] grid, Position p, int moves) {\n        Position downP = new Position(p.x1 + 1, p.y1, p.x2 + 1, p.y2, moves + 1);\n        if (validateValidP(grid, downP)) {\n            return downP;\n        }\n        return null;\n    }\n    private Position moveClock(int[][] grid, Position p, int moves) {\n        // Not horizontal\n        if (p.y1 != p.y2 + 1) {\n            return null;\n        }\n        if (p.x1 + 1 >= n || grid[p.x1 + 1][p.y1] == 1 || p.x2 + 1 >= n || grid[p.x2 + 1][p.y2] == 1) {\n            return null; // Blocker\n        }\n        Position clockP = new Position(p.x1 + 1, p.y1 - 1, p.x2, p.y2, moves + 1);\n        // Cannot move back to same position in next position\n        if (validateValidP(grid, clockP)) {\n            return clockP;\n        }\n        return null;\n    }\n    private Position moveCounterClock(int[][] grid, Position p, int moves) {\n        // Not Vertical\n        if (p.x1 != p.x2 + 1) {\n            return null;\n        }\n        if (p.y1 + 1 >= n || grid[p.x1][p.y1 + 1] == 1 || p.y2 + 1 >= n || grid[p.x2][p.y2 + 1] == 1) {\n            return null; // Blocker\n        }\n        Position counterClockP = new Position(p.x1 - 1, p.y1 + 1, p.x2, p.y2, moves + 1);\n        if (validateValidP(grid, counterClockP)) {\n            return counterClockP;\n        }\n        return null;\n    }\n    private boolean validateWin(Position p) {\n        if (p.x1 == n - 1 && p.y1 == n - 1\n            && p.x2 == n - 1 && p.y2 == n - 2) {\n            return true;\n        }\n        return false;\n    }\n    private boolean validateValidP(int[][] grid, Position p) {\n        if (p.x1 < 0 || p.x1 >= n \n            || p.x2 < 0 || p.x2 >= n\n           || p.y1 < 0 || p.y1 >= n\n            || p.y2 < 0 || p.y2 >= n) {\n            return false;\n        }\n        if (grid[p.x1][p.y1] == 1 || grid[p.x2][p.y2] == 1) {\n            return false;\n        }\n        return visited.add(p);\n    }\n}\n```
[]