[JAVA] BFS with comments
visited array is 3 dimentional, box x,y index and last move direction.\n2. as we have 4 direcitons, when ierate, just use index as direction.\n3. for each next 
1. visited array is 3 dimentional, box x,y index and last move direction.\n2. as we have 4 direcitons, when ierate, just use index as direction.\n3. for each next move, we need to check next box position and next player position is in bound.\n4. an additional bfs function to check the player can mvoe the target player postion or not.\n```\nclass Solution {\n    public int minPushBox(char[][] grid) {\n        final Queue<int[]> queue = new LinkedList<>();\n        final boolean[][][] visited =\n                new boolean[grid.length][grid[0].length][4];\n        final int[] target = new int[2];\n        final int[] player = new int[2];\n        final int[] box = new int[2];\n        for (int i = 0; i < grid.length; i++) {\n            for (int j = 0; j < grid[0].length; j++) {\n                if (grid[i][j] == \'T\') {\n                    target[0] = i;\n                    target[1] = j;\n                    grid[i][j] = \'.\';\n                }\n                if (grid[i][j] == \'S\') {\n                    player[0] = i;\n                    player[1] = j;\n                    grid[i][j] = \'.\';\n                }\n                if (grid[i][j] == \'B\') {\n                    box[0] = i;\n                    box[1] = j;\n                    grid[i][j] = \'.\';\n                }\n            }\n        }\n        queue.offer(new int[]{\n                box[0], box[1], player[0], player[1]\n        });\n        int level = 0;\n        while (!queue.isEmpty()) {\n            final int currentSize = queue.size();\n            // iterate by level\n            for (int size = 0; size < currentSize; size++) {\n                final int[] current = queue.poll();\n                if (current[0] == target[0] &&\n                        current[1] == target[1]\n                ) {\n                    return level;\n                }\n                for (int index = 0; index < 4; index++) {\n                    // next box position\n                    final int nextX = current[0] + deltaX[index];\n                    final int nextY = current[1] + deltaY[index];\n                    // next player position is opposite to box\n                    final int playerX = current[0] - deltaX[index];\n                    final int playerY = current[1] - deltaY[index];\n                    // next box player should be in bound, equals to \'.\'\n                    // player can move from current player position to (playerX,playerY)\n                    if (inBound(grid, nextX, nextY) &&\n                            inBound(grid, playerX, playerY) &&\n                            !visited[nextX][nextY][index] &&\n                            grid[nextX][nextY] == \'.\' &&\n                            grid[playerX][playerY] == \'.\' &&\n                            canPush(grid, playerX, playerY, current[2], current[3], current[0], current[1])\n                    ) {\n                        queue.offer(new int[]{nextX, nextY, playerX, playerY});\n                        visited[nextX][nextY][index] = true;\n                    }\n                }\n            }\n            ++level;\n        }\n        return -1;\n    }\n\n    // as we mark box as \'.\', so we need its position to block player\'s moves\n    private boolean canPush(\n            char[][] grid,\n            int targetX,\n            int targetY,\n            int x,\n            int y,\n            int boxX,\n            int boxY) {\n        final Queue<int[]> queue = new LinkedList<>();\n        final boolean[][] visited =\n                new boolean[grid.length][grid[0].length];\n        queue.offer(new int[]{x, y});\n        visited[x][y] = true;\n        while (!queue.isEmpty()) {\n            final int[] current = queue.poll();\n            if (current[0] == targetX && current[1] == targetY) {\n                return true;\n            }\n            for (int index = 0; index < 4; index++) {\n                final int nextX = current[0] + deltaX[index];\n                final int nextY = current[1] + deltaY[index];\n                if (inBound(grid, nextX, nextY) &&\n                        !visited[nextX][nextY] &&\n                        grid[nextX][nextY] == \'.\' &&\n                        (nextX != boxX || nextY != boxY)\n                ) {\n                    queue.offer(new int[]{nextX, nextY});\n                    visited[nextX][nextY] = true;\n                }\n            }\n        }\n        return false;\n    }\n\n\n    private final int[] deltaX = {0, 0, -1, 1};\n    private final int[] deltaY = {-1, 1, 0, 0};\n\n    private boolean inBound(\n            char[][] grid,\n            int x,\n            int y\n    ) {\n        return x >= 0 && y >= 0 && x < grid.length && y < grid[0].length;\n    }\n}\n```
['Breadth-First Search', 'Java']