public int collapseAbove(int row) {
		if (row >= rows) { return 0; }
		
		// Loop through the row to check if it's empty, full, or partially full
		boolean full = true, empty = true;
		for (int j = 0; j < cols; ++j) {
			if (gridCells[row][j].getState() != GridState.BLOCK) {
				full = false;
			}
			else {
				empty = false;
			}
		}
		
		// Base case 1: The row is full, shift all rows above down 1
		if (full) {
			int above = collapseAbove(row + 1);
			
			empty = false;
			for (int i = row; i < rows - 1 && !empty; ++i) {
				empty = true;
				for (int j = 0; j < cols; ++j) {
					if (gridCells[i + 1][j].getState() == GridState.BLOCK) {
						gridCells[i][j].Block(gridCells[i + 1][j].getBlock());
						empty = false;
					}
					else {
						gridCells[i][j].Clear();
					}
				}
			}
			
			return ++above;
		}
		
		// Base case 2: The row is empty, halt recursive calls 
		if(empty) {
			return 0;
		}
		
		// Base case 3: The row is partially full, continue recursive search
		return collapseAbove(row + 1);
	}