Complete the Connect 4 in GridWorld practice problem before reviewing the solution.

Review the Connect 4 solution with AP CS Tutor Brandon Horn.

The method documentation from the original practice problem has been omitted.

public class BoardUtilities
{
    private BoundedGrid<Disc> board;

    public BoardUtilities(BoundedGrid<Disc> board)
    {
        this.board = board;
    }

    public int countDiscs(Location loc, boolean color, int dir)
    {
        Location nextLoc = loc.getAdjacentLocation(dir);

        if ( ! board.isValid(nextLoc) || board.get(nextLoc) == null ||
                board.get(nextLoc).color() != color)
            return 0;

        return 1 + countDiscs(nextLoc, color, dir);
    }

    public int firstEmptyRow(int col)
    {
        Location firstEmptySpot = null;

        // find first empty spot in column from bottom
        for (int row = board.getNumRows() - 1; row >= 0 && firstEmptySpot == null; row--)
        {
            Location currentSpot = new Location(row, col);
            
            if (board.get(currentSpot) == null)
                firstEmptySpot = currentSpot;
        }

        return firstEmptySpot != null ? firstEmptySpot.getRow() : -1;
    }

    public boolean wouldWin(boolean color, int col)
    {
        return connectingDiscs(color, col) >= 4;
    }

    public int connectingDiscs(boolean color, int col)
    {
        int row = firstEmptyRow(col);

        if (row == -1) // column is full
            return 0;

        Location dropLocation = new Location(row, col);

        int maximumConnectingDiscs = 0;

        for (int direction = 0; direction <= 135; direction += 45)
        {
            int connectingDiscs = countDiscs(dropLocation, color, direction) +
                    countDiscs(dropLocation, color, direction + Location.HALF_CIRCLE);
            
            if (connectingDiscs > maximumConnectingDiscs)
                maximumConnectingDiscs = connectingDiscs;
        }

        return maximumConnectingDiscs + 1;
    }

    public ArrayList<Integer> validMoves()
    {
        ArrayList<Integer> validMoves = new ArrayList<Integer>();

        for (int col = 0; col < board.getNumCols(); col++)
            if (firstEmptyRow(col) != -1)
                validMoves.add(col);

        return validMoves;
    }

    public boolean turn()
    {
        int blueDiscs = 0;
        int redDiscs = 0;

        for (Location loc : board.getOccupiedLocations())
        {
            if (board.get(loc).color())
                blueDiscs++;
            else
                redDiscs++;
        }

        return blueDiscs == redDiscs;
    }
}