/// <summary> /// Generate a Word to (potentially) be played on the board based on the anagrams available and /// the adjacent tiles. /// </summary> /// <param name="word"></param> /// <param name="adjacentTile"></param> /// <param name="direction"></param> /// <returns></returns> private Word GenerateWordInDirection(string word, ScrabbleTile adjacentTile, MovementDirection direction) { var adjacent = adjacentTile.Text; int adjacentIndex = word.IndexOf(adjacent); int sx, ex, sy, ey = 0; switch (direction) { case MovementDirection.Down: // Vertically placing the word sx = adjacentTile.XLoc; ex = adjacentTile.XLoc; sy = adjacentTile.YLoc - adjacentIndex; ey = adjacentTile.YLoc + (word.Length - 1 - adjacentIndex); break; case MovementDirection.Across: // Horizontally placing the word sx = adjacentTile.XLoc - adjacentIndex; ex = adjacentTile.XLoc + (word.Length - 1 - adjacentIndex); sy = adjacentTile.YLoc; ey = adjacentTile.YLoc; break; default: throw new Exception($"Unsupported movement direction to generate words for {direction}"); } var w = new Word { Text = word, StartX = sx, EndX = ex, StartY = sy, EndY = ey, Tiles = new List <ScrabbleTile>() }; for (int x = sx; x <= ex; x++) { for (int y = sy; y <= ey; y++) { if (x < 0 || x >= ScrabbleForm.BOARD_WIDTH - 1 || y < 0 || y >= ScrabbleForm.BOARD_HEIGHT - 1) { return(null); } w.Tiles.Add(ScrabbleForm.TileManager.Tiles[x, y]); } } //w.Score = WordScorer.ScoreWord(w); w.Score = WordScorer.RawWordScore(word); return(w); }
/// <summary> /// For all the available words in the scrabble dictionary, /// check which ones can be made from the provided string of letters. /// </summary> /// <param name="letters"></param> /// <returns></returns> public List <Word> Anagrams(string letters, ScrabbleTile adjacentTile = null) { // If we have been provided an adjacent tile, then we can also use that to make words. if (adjacentTile != null) { letters += adjacentTile.Text; } var words = new List <Word>(); foreach (var w in ScrabbleForm.WordValidator.ValidWords) { // If a certain letter must be in the output then ensure the word we are making contains it if (adjacentTile != null && !w.Contains(adjacentTile.Text)) { continue; } if (CanMakeWord(w, letters)) { if (adjacentTile != null) { var vertical = GenerateWordInDirection(w, adjacentTile, MovementDirection.Down); if (vertical != null && !words.Contains(vertical)) { words.Add(vertical); } var horizontal = GenerateWordInDirection(w, adjacentTile, MovementDirection.Across); if (horizontal != null && !words.Contains(horizontal)) { words.Add(horizontal); } } else { var word = new Word { Text = w, Score = WordScorer.RawWordScore(w) }; if (!words.Contains(word)) { words.Add(word); } } } } return(words.OrderByDescending(w => w.Score).ThenByDescending(w => w.Text.Length).ToList()); }
/// <summary> /// Validate all the words on the board. /// </summary> /// <returns></returns> public MoveResult ValidateAllWordsInPlay() { var words = new List <Word>(); for (int x = 0; x < ScrabbleForm.BOARD_WIDTH; x++) { for (int y = 0; y < ScrabbleForm.BOARD_HEIGHT; y++) { if (!string.IsNullOrEmpty(ScrabbleForm.TileManager.Tiles[x, y].Text) && ScrabbleForm.TileManager.Tiles[x, y].TileInPlay) { foreach (var w in GetSurroundingWords(x, y)) { // Todo: need to allow duplicated words if the word actually has been played twice // Think this is sorted, just need to test it. if (!words.Contains(w)) { words.Add(w); } } } } } foreach (var w in words) { w.Tiles = GetWordTiles(w); w.Score = WordScorer.ScoreWord(w); w.Valid = CheckWord(w); w.SetValidHighlight(); //MessageBox.Show($"{w} valid: {w.Valid}"); } return(new MoveResult { TotalScore = words.Sum(w => w.Score), Words = words, Valid = words.All(w => w.Valid) }); }