/// <summary>
        /// Recherche des différents coups admis
        /// </summary>
        public List <Word> FindMoves(Player p, int maxWordCount = 100, bool sortByBestScore = true)
        {
            Game.IsTransposed = false;
            var currentRack = p.Rack;

            NbPossibleMoves = 0;
            NbAcceptedMoves = 0;
            LegalWords.Clear();
            LegalWords.AddRange(Game.Player1.Moves);
            LegalWords.AddRange(Game.Player2.Moves);
            var backupGrid = Game.Grid.Copy();

            Game.Grid = DetectTiles(Game.Grid);

            // Rechercher pour chaque case précédemment identifiée les différents coups possibles et les enregistrer
            Game.Grid = FindMovesPerAnchor(p, Game.Grid);
            // Recherche des coups verticaux
            // par transposition de la grille, on refait tout le processus
            Game.Grid = backupGrid;
            p.Rack    = currentRack;

            Game.Grid = Game.Grid.Transpose(Game);
            Game.Grid = DetectTiles(Game.Grid);
            // Rechercher pour chaque case précédemment identifiée les différents coups possibles et les enregistrer
            Game.Grid = FindMovesPerAnchor(p, Game.Grid);

            var ret = LegalWords;

            //on remet la grille à son état initial
            Game.Grid         = backupGrid;
            Game.IsTransposed = false;

            if (sortByBestScore)
            {
                return(ret.OrderByDescending(t => t.Points).Take(maxWordCount).ToList());
            }
            else
            {
                return(ret.OrderByDescending(t => t.Text.Length).Take(maxWordCount).ToList());
            }

            //if (p.Rack.Any())
            //{
            //    // Les lettres non utilisées sont "reversées dans le sac"
            //    foreach (var l in p.Rack)
            //        Game.Bag.PutBackLetter(l);
            //}
        }
        /// <summary>
        /// Cette procédure ajoute un coup à la liste des coups admis recensés
        /// en enregistrant la place où le coup est joué
        /// s'il est joué horizontalement ou verticalement
        /// le mot formé
        /// le point que le coup rapporte
        /// </summary>
        /// <param name="word"></param>
        /// <param name="t"></param>
        private void Add(VTile[,] grid, string word, int ligne, int colonne, MovementDirection direction)
        {
            int multiplier         = 1;
            int horizontalPoints   = 0;
            int verticalPoints     = 0;
            int points             = 0;
            int debutCol           = colonne - word.Length;
            int UsedDraughtLetters = 0;

            var startTile = direction == MovementDirection.Across ? grid[ligne, debutCol] : grid[debutCol, ligne];
            var newWord   = new Word(Game)
            {
                StartTile = startTile,
                Direction = direction,
                Text      = word,
            };

            if (!LegalWords.Any(pw => pw.Equals(newWord)))
            {
                for (int j = 0; j < word.Length; j++)
                {
                    var tile = grid[ligne, debutCol + j];
                    var L    = word[j];
                    if (tile.IsEmpty)
                    {
                        // Le calcul des points prend en compte les cases bonus non encore utilisées
                        // Il faut noter que seules les lettres du tirage permettent de bénéficier des bonus
                        // Les points verticaux ont été précalculés au moment du recensement des contrôleurs
                        if (char.IsUpper(L))
                        {
                            horizontalPoints += Game.Alphabet.Find(c => c.Char == char.ToUpper(L)).Value *tile.LetterMultiplier;
                            verticalPoints   += tile.Controlers.ContainsKey(L - Dictionnaire.AscShiftBase0) ? tile.Controlers[L - Dictionnaire.AscShiftBase0] : 0;
                        }

                        else
                        {
                            if (tile.Controlers.ContainsKey(((int)char.ToUpper(L)) - Dictionnaire.AscShiftBase0) && tile.Controlers[((int)char.ToUpper(L)) - Dictionnaire.AscShiftBase0] > 0)
                            {
                                verticalPoints += tile.Controlers[((int)char.ToUpper(L)) - Dictionnaire.AscShiftBase0] - Game.AlphabetWWFAvecJoker.Find(c => c.Char == char.ToUpper(L)).Value
                                                  *tile.LetterMultiplier *tile.WordMultiplier;
                            }
                        }
                        multiplier *= tile.WordMultiplier;
                        UsedDraughtLetters++;
                    }
                    else
                    {
                        if (char.IsUpper(L))
                        {
                            horizontalPoints += Game.Alphabet.Find(c => c.Char == char.ToUpper(L)).Value;
                        }
                    }
                }
                // L'utilisation des 7 lettres du tirage rapporte en plus 50 points de bonus
                points = horizontalPoints * multiplier + verticalPoints + (UsedDraughtLetters == 7 ? 50 : 0);

                NbPossibleMoves++;
                //if (LegalWords.Any() && points < LegalWords.Min(l => l.Points)) return;
                // Tri et mise en forme des coups
                //if (points <= MinPoint) return;
                newWord.Points = points;

                newWord.Scramble = UsedDraughtLetters == 7;
                //if (!LegalWords.Any(w => w.Equals(newWord)) && !PlayedWords.Any(pw => pw.Equals(newWord)))

                LegalWords.Add(newWord);
                NbAcceptedMoves++;
            }
        }