//Check for tiles which disqualify square (1,2), otherwise for a connection which qualifies it (3)
        static bool CheckSquare(Grid grid, int top, int bottom, int column, ref int contactRow)
        {
            if ((!grid.GetSquare(Math.Max(top - 1, 0), column).IsBlank && top > 0)) // 1)Check square above for letter
                { return false;}

            for (var row = top; row < BoardSize; row++) // 2)Check for continuous column of letters to bottom (Includes bottom row)
            {
                if (grid.GetSquare(row, column).IsBlank)
                {
                    break;
                }
                if (!grid.GetSquare(row, column).IsBlank && row == BoardSize - 1)
                {
                    return false;
                }
            }

            for (var row = top; row < bottom + 1; row++) // 3)Check letters-by-3 box (squares in column and adjacent columns on either side)
            {
                if (grid.GetSquare(row, Math.Max(column - 1, 0)).Letter.ToString(CultureInfo.InvariantCulture) + grid.GetSquare(row, column).Letter + grid.GetSquare(row, Math.Min(BoardSize - 1, column + 1)).Letter != "   ")
                {
                    contactRow = row - top + 1;
                    return true;
                }
            }

            if (bottom != BoardSize - 1 && !grid.GetSquare(bottom + 1, column).IsBlank) // 3)Check square below bottom-most reach
            {
                contactRow = bottom - top + 2;
                return true;
            }

            return false;
        }
        public Mould(Grid grid, int letterCount, int row, int column, int boardSize)
        {
            _mould = new List<char>();

            for (var r = row; r < boardSize; r++)
            {
                _mould.Add(grid.GetSquare(r, column).Letter);
            }

            var blanks = _mould.Count(i => i == Constants.Blank);

            if (blanks > letterCount)
            {
                for (var r = _mould.Count - 1; r > -1; r--)
                {
                    if (blanks == letterCount) { break; }
                    if (_mould[r] == Constants.Blank)
                    {
                        _mould.RemoveAt(r);
                        blanks--;
                        continue;
                    }

                    _mould.RemoveAt(r);
                }
            }
        }
        public Grid RotateCounterClockwise()
        {
            var rotatedGrid = new Grid(_grid.GetLength(0));

            for (var r = 0; r < _grid.GetLength(0); r++)
            {
                for (var c = 0; c < _grid.GetLength(1); c++)
                {
                    rotatedGrid.SetSquare(r, c, GetSquare(_grid.GetLength(1) - 1 - c, r));
                }
            }

            return rotatedGrid;
        }
            public Fill(int boardSize)
            {
                BoardFilled = BoardEmpty;

                var letters = new List<string>
                {
                    //012345678901234
                    "               ", //0
                    "               ", //1
                    "               ", //2
                    "               ", //3
                    "               ", //4
                    "               ", //5
                    "choleric       ", //6
                    "       a       ", //7 M
                    "     bottle    ", //8
                    "               ", //9
                    "               ", //10
                    "               ", //11
                    "               ", //12
                    "               ", //13
                    "               ", //14
                    //012345678901234
                };

                for (var i = 0; i < boardSize; i++)
                {
                    var chrs = letters[i].ToCharArray().ToList();
                    for (var j = 0; j < boardSize; j++)
                    {
                        BoardFilled.GetSquare(i, j).Row = i;
                        BoardFilled.GetSquare(i, j).Column = j;
                        BoardFilled.GetSquare(i, j).Letter = chrs[j];
                        BoardFilled.GetSquare(i, j).Score = Program.LetterValues(BoardFilled.GetSquare(i, j).Letter.ToString(CultureInfo.InvariantCulture).ToCharArray().ToList())[0]; //TODO: !!
                        BoardFilled.GetSquare(i, j).LetterBonus = BoardFilled.GetSquare(i, j).LetterBonus == 0 ? 1 : BoardFilled.GetSquare(i, j).LetterBonus;
                        BoardFilled.GetSquare(i, j).WordBonus = BoardFilled.GetSquare(i, j).WordBonus == 0 ? 1 : BoardFilled.GetSquare(i, j).WordBonus;
                    }
                }
            }
        static Grid GetGrid(Grid board)
        {
            var letterFrequencyTotal = new List<int>(); //Cumulative letter frequency for board. Max # of each tile allowed.
            for (var row = 0; row < BoardSize; row++)
            {
                for (; ; )
                {
                    var letterFrequencyRow = new List<int>(letterFrequencyTotal);

                    Console.Write("Enter Row {0} letters: ", row + 1);
                    var rowLetters = (Console.ReadLine().ToLower().ToList());

                    if (rowLetters.Count < BoardSize) //Fill rest of row with blanks
                    {
                        for (var j = rowLetters.Count; j < BoardSize; j++)
                        {
                            rowLetters.Add(Constants.Blank);
                        }
                    }

                    letterFrequencyRow = LetterFreq(rowLetters, letterFrequencyRow, BoardSize); //Get letter frequencies of current row

                    if (!LettersCheck(rowLetters, letterFrequencyRow, BoardSize)) { continue; } //Check validity of entered characters

                    letterFrequencyTotal = letterFrequencyRow;

                    for (var column = 0; column < BoardSize; column++) //Add row letters to board
                    {
                        board.GetSquare(row, column).Letter = rowLetters[column];
                    }

                    break;
                }
            }

            return board;
        }
 static void WriteBoard(Grid board)
 {
     Console.WriteLine(" 123456789012345");
     for (var i = 0; i < BoardSize; i++)
     {
         Console.Write("|");
         for (var j = 0; j < BoardSize - 1; j++)
         {
             Console.Write((board.GetSquare(i, j)).Letter.ToString(CultureInfo.InvariantCulture).ToUpper());
         }
         Console.WriteLine((board.GetSquare(i, BoardSize - 1)).Letter.ToString(CultureInfo.InvariantCulture).ToUpper() + "| {0}", i + 1);
     }
 }
        static List<Word> WordSolver(Grid grid, List<char> letters, int row, int column, int contactRow, Direction direction)
        {
            var mould = new Mould(grid, letters.Count, row, column, BoardSize); //Find 'mould' (line of empty and filled squares down or across) for current square, eg. "  C D"

            var words = new List<Word>();

            var lowerIndex = Dictionary.Lengths[Math.Max(contactRow - 2, 0)]; //Check only dictionary words of lengths in applicable range
            var upperIndex = Dictionary.Lengths[mould.Count - 1] + 1;

            for (var i = lowerIndex; i < upperIndex; i++)
            {
                var dictionaryWord = Dictionary.Dict[i];
                if (dictionaryWord.Length > mould.Count) { continue; }

                var word = dictionaryWord.ToCharArray().ToList();
                var blankLetters = new List<char>();

                if (!mould.MouldFits(word) || !mould.WordFits(contactRow, letters, word, ref blankLetters) || !PerpendicularWords(grid, word, row, column, direction))
                {
                    continue;
                }

                //Blank tiles have 0 score. Thus when used for a letter that occurs more than once multiple words must be recored, e.g LOSSE#, LOS#ES and LO#SES
                var wordBlanks = mould.GenerateBlankVariations(word, blankLetters);

                foreach (var w in wordBlanks) //Add each word to final list
                {
                    words.Add(new Word
                    {
                        Row = row,
                        Column = column,
                        Direction = direction,
                        Letters = word,
                        Wrd = string.Concat(word),
                        Scores = LetterValues(w),
                    });
                }
            }

            for (var w = 0; w < words.Count; w++) //Score each word
            {
                words[w] = WordScorer(words[w], grid);
                if (direction == Direction.Across) //Reset coordinates of across words due to rotation
                {
                    var temp = words[w].Row;
                    words[w].Row = BoardSize - 1 - words[w].Column;
                    words[w].Column = temp;
                }
            }

            return words;
        }
        static Word WordScorer(Word word, Grid grid)
        {
            var totalScore = 0;
            var totalWordMultiplier = 1; //Total word multiplier for base word score
            var baseScore = 0; //Basic score of actual word before final word multiplication
            var letterCount = 0; //Check if all letters are used for 35 bonus

            for (var r = 0; r < word.Letters.Count; r++)
            {
                var letterMultiplier = grid.GetSquare(r + word.Row, word.Column).IsBlank ? grid.GetSquare(r + word.Row, word.Column).LetterBonus : 1; //Determine if square letter muliplier is applicable
                var wordMultiplier = grid.GetSquare(r + word.Row, word.Column).IsBlank ? grid.GetSquare(r + word.Row, word.Column).WordBonus : 1; //Determine if square word multiplier is applicable

                totalWordMultiplier *= wordMultiplier; //Add square word multiplier to total word multiplier

                baseScore += word.Scores[r] * letterMultiplier; //Add current letter score to base word score

                if (!grid.GetSquare(r + word.Row, word.Column).IsBlank) { continue; } //Existing letter - perpendicular word doesn't score

                letterCount++;

                var crossWord = word.Scores[r] * letterMultiplier; //Letter value times letter bonus

                var count = 0; //Count of perpendicular tiles. Needed due to potential blank tiles with 0 score.
                for (var c = word.Column - 1; c > -1; c--) //Add letter scores for perp word to left
                {
                    if (grid.GetSquare(r + word.Row, c).IsBlank) { break; }
                    crossWord += grid.GetSquare(r + word.Row, c).Score;
                    count++;
                }
                for (var c = word.Column + 1; c < BoardSize; c++) //Add letter scores for perp word to right
                {
                    if (grid.GetSquare(r + word.Row, c).IsBlank) { break; }
                    crossWord += grid.GetSquare(r + word.Row, c).Score;
                    count++;
                }
                if (count == 0) { continue; } //No perpendicular word

                totalScore += crossWord * wordMultiplier; //Add each perp word score to total score
            }

            totalScore += baseScore * totalWordMultiplier; //Add base word score to total score
            if (letterCount == 7) { totalScore += 35; }
            word.WordScore = totalScore;

            return word;
        }
        static List<Word> SquareRunThrough(Grid board, List<char> letters, Direction direction)
        {
            var words = new List<Word>();

            var limitsLtRtUpLw = Limits(board); //Limits let code ignore checking large sections of board

            for (var row = 0; row < limitsLtRtUpLw[3]; row++)
            {
                for (var column = limitsLtRtUpLw[0]; column < limitsLtRtUpLw[1] + 1; column++)
                {
                    var contactRow = BoardSize;

                    if (!CheckSquare(board, row, Math.Min(row + letters.Count - 1, BoardSize - 1), column, ref contactRow))
                    {
                        continue;
                    }

                    words.AddRange(WordSolver(board, letters, row, column, contactRow, direction));
                }
            }

            var wordsOrdered = from element in words //Order across words by square (down words ordered incidentally)
                orderby element.Row
                select element;

            return wordsOrdered.ToList();
        }
        //Check any perpendicular words are legal
        static bool PerpendicularWords(Grid grid, List<char> word, int row, int column, Direction direction)
        {
            for (var r = 0; r < word.Count; r++) //Check perp word at each letter
            {
                var perpWord = word[r].ToString(CultureInfo.InvariantCulture);
                for (var c = column - 1; c > -1; c--) //Construct perp word with letters to left
                {
                    if (grid.GetSquare(r + row, c).IsBlank) { break; }
                    perpWord = grid.GetSquare(r + row, c).Letter + perpWord;
                }
                for (var c = column + 1; c < BoardSize; c++) //Add letters to right
                {
                    if (grid.GetSquare(r + row, c).IsBlank) { break; }
                    perpWord += grid.GetSquare(r + row, c).Letter.ToString(CultureInfo.InvariantCulture);
                }

                if (perpWord.Length == 1) { continue; } //I.E. no adjacent letters

                var dictionary = direction == Direction.Down ? new List<string>(Dictionary.Dict) : new List<string>(Dictionary.DictRev); //Rotation for across words means perp words are reversed. Use dictionary with reverse words.
                var lowerIndex = Dictionary.Lengths[perpWord.Length - 2]; //Indices to only check dictionary words of exact length
                var upperIndex = Dictionary.Lengths[perpWord.Length - 1];

                for (var w = lowerIndex; w < upperIndex + 1; w++ )
                {
                    if (perpWord == dictionary[w])
                    {
                        break;
                    }
                    if (w == upperIndex && perpWord != dictionary[w] )
                    {
                        return false;
                    }
                }
            }

            return true;
        }
        static List<int> Limits(Grid grid)
        {
            var lts = new List<int> { BoardSize - 1, 0, BoardSize - 1, 0 }; //Left-Column/Right-Column/Upper-Row/Lower-Row bounds

            for (var r = 0; r < BoardSize; r++)
            {
                for (var c = 0; c < BoardSize; c++)
                {
                    var chr = Regex.IsMatch(grid.GetSquare(r,c).Letter.ToString(CultureInfo.InvariantCulture), @"[a-z]");
                    if (chr && c <= lts[0]){lts[0] = Math.Max(c - 1, 0);}
                    if (chr && c >= lts[1]){lts[1] = Math.Min(c + 1, BoardSize - 1);}
                    if (chr && r <= lts[2]){lts[2] = Math.Max(r - 1, 0);}
                    if (chr && r >= lts[3]){lts[3] = Math.Min(r + 1, BoardSize - 1);}
                }
            }

            return lts;
        }