/// <summary> /// Scores a <see cref="Play"/> that was already added to the board. /// </summary> /// <param name="play">The <see cref="Play"/> to be scored.</param> /// <param name="shouldRemoveMultipliers">Tells whether the <see cref="GameBoardSquare"/>s which are being filled by /// the <see cref="LetterTile"/>s in play should have their score multipliers set to 1.</param> /// <returns>The score of a <see cref="Play"/> that was already added to the board.</returns> public int ScorePlay(Play play, bool shouldRemoveMultipliers) { // Make sure the play is already on the board. for (int i = 0; i < play.GetParallelListLength(); ++i) { int x = play.GetCoordinateX(i); int y = play.GetCoordinateY(i); if (!this.boardGrid[x, y].ContainedLetterTile.Equals(play.GetLetterTile(i))) { throw new InvalidPlayException(); } } int totalPoints = 0; // If the play consists of only one LetterTile, score vertically and horizontally around it. if (play.GetParallelListLength() == 1) { totalPoints += this.ScoreOneHorizontalWord(play.GetCoordinateX(0), play.GetCoordinateY(0)); totalPoints += this.ScoreOneVerticalWord(play.GetCoordinateX(0), play.GetCoordinateY(0)); } else if (play.GetCoordinateY(0) == play.GetCoordinateY(1)) { // Otherwise, if the play is a horizontal play, score all of the vertical words that branch off from that // play, and then score the horizontal word in play. int horizontalWordMultiplier = 1; int horizontalWordPoints = 0; for (int i = 0; i < play.GetParallelListLength(); ++i) { horizontalWordMultiplier *= this.boardGrid[play.GetCoordinateX(i), play.GetCoordinateY(i)].WordMultiplier; } for (int i = 0; i < play.GetParallelListLength(); ++i) { totalPoints += this.ScoreOneVerticalWord(play.GetCoordinateX(i), play.GetCoordinateY(i)); horizontalWordPoints += this.ScoreOneTile(play.GetCoordinateX(i), play.GetCoordinateY(i)); } // Get the points from the adjacent squares to the left and right of the played letters. int minX = play.GetCoordinateX(0); int maxX = minX; for (int i = 0; i < play.GetParallelListLength(); ++i) { if (minX > play.GetCoordinateX(i)) { minX = play.GetCoordinateX(i); } if (maxX < play.GetCoordinateX(i)) { maxX = play.GetCoordinateX(i); } } // Go left. int count = 1; while (true) { if (minX - count < 0 || this.boardGrid[minX - count, play.GetCoordinateY(0)].IsEmpty()) { break; } else { horizontalWordPoints += this.ScoreOneTile(minX - count, play.GetCoordinateY(0)); ++count; } } // Go right. count = 1; while (true) { if (maxX + count > 14 || this.boardGrid[maxX + count, play.GetCoordinateY(0)].IsEmpty()) { break; } else { horizontalWordPoints += this.ScoreOneTile(maxX + count, play.GetCoordinateY(0)); ++count; } } // Check for gaps between letters in the play, and score them. List<int> coordsX = new List<int>(); for (int i = 0; i < play.GetParallelListLength(); ++i) { coordsX.Add(play.GetCoordinateX(i)); } coordsX.Sort(); count = 1; for (int i = 0; i < coordsX.Count - 1; ++i) { while (coordsX[i] + count < coordsX[i + 1]) { horizontalWordPoints += this.ScoreOneTile(coordsX[i] + count, play.GetCoordinateY(0)); ++count; } count = 1; } horizontalWordPoints *= horizontalWordMultiplier; totalPoints += horizontalWordPoints; } else { // Otherwise, if the play is a vertical play, score all of the horizontal words that branch off from that // play, and then score the vertical word in play. int verticalWordMultiplier = 1; int verticalWordPoints = 0; for (int i = 0; i < play.GetParallelListLength(); ++i) { verticalWordMultiplier *= this.boardGrid[play.GetCoordinateX(i), play.GetCoordinateY(i)].WordMultiplier; } for (int i = 0; i < play.GetParallelListLength(); ++i) { totalPoints += this.ScoreOneHorizontalWord(play.GetCoordinateX(i), play.GetCoordinateY(i)); verticalWordPoints += this.ScoreOneTile(play.GetCoordinateX(i), play.GetCoordinateY(i)); } // Get the points from the adjacent squares above and below the played letters. int minY = play.GetCoordinateY(0); int maxY = minY; for (int i = 0; i < play.GetParallelListLength(); ++i) { if (minY > play.GetCoordinateY(i)) { minY = play.GetCoordinateY(i); } if (maxY < play.GetCoordinateY(i)) { maxY = play.GetCoordinateY(i); } } // Go up. int count = 1; while (true) { if (minY - count < 0 || this.boardGrid[play.GetCoordinateX(0), minY - count].IsEmpty()) { break; } else { verticalWordPoints += this.ScoreOneTile(play.GetCoordinateX(0), minY - count); ++count; } } // Go down. count = 1; while (true) { if (maxY + count > 14 || this.boardGrid[play.GetCoordinateX(0), maxY + count].IsEmpty()) { break; } else { verticalWordPoints += this.ScoreOneTile(play.GetCoordinateY(0), maxY + count); ++count; } } // Check for gaps between letters in the play, and score them. List<int> coordsY = new List<int>(); for (int i = 0; i < play.GetParallelListLength(); ++i) { coordsY.Add(play.GetCoordinateY(i)); } coordsY.Sort(); count = 1; for (int i = 0; i < coordsY.Count - 1; ++i) { while (coordsY[i] + count < coordsY[i + 1]) { verticalWordPoints += this.ScoreOneTile(play.GetCoordinateX(0), coordsY[i] + count); ++count; } count = 1; } verticalWordPoints *= verticalWordMultiplier; totalPoints += verticalWordPoints; } if (shouldRemoveMultipliers) { // Clear the word and letter multipliers of the GameBoardSquares in the play. for (int i = 0; i < play.GetParallelListLength(); ++i) { this.boardGrid[play.GetCoordinateX(i), play.GetCoordinateY(i)].RemoveScoreMultipliers(); } } // Give the 50 point bonus for using 7 LetterTiles. if (play.GetParallelListLength() == 7) { totalPoints += 50; } return totalPoints; }
/// <summary> /// Adds a play to <see cref="squaresList"/>. The play is not scored. /// </summary> /// <param name="play">The <see cref="Play"/> to be added to the <see cref="Board"/>.</param> public void AddPlayToBoard(Play play) { if (!this.PlayIsValid(play)) { throw new InvalidPlayException(); } for (int i = 0; i < play.GetParallelListLength(); ++i) { this.boardGrid[play.GetCoordinateX(i), play.GetCoordinateY(i)].InsertLetterTile(play.GetLetterTile(i)); } this.lastPlay = play; this.lastPlayIsNull = false; }
/// <summary> /// Gets a list of all the words created by a given play. /// </summary> /// <param name="play">The play being checked.</param> /// <returns>The list of words created by the play.</returns> public List<string> GetWordsInPlay(Play play) { List<string> words = new List<string>(); bool isVerticalPlay; // Make sure that all of the LetterTiles in the play are already on the board. for (int i = 0; i < play.GetParallelListLength(); ++i) { if (this.boardGrid[play.GetCoordinateX(i), play.GetCoordinateY(i)].IsEmpty()) { throw new InvalidPlayException(); } if (!this.boardGrid[play.GetCoordinateX(i), play.GetCoordinateY(i)].ContainedLetterTile.Equals(play.GetLetterTile(i))) { throw new InvalidPlayException(); } } if (play.GetParallelListLength() == 1 || play.GetCoordinateX(0) == play.GetCoordinateX(1)) { isVerticalPlay = true; } else { isVerticalPlay = false; } int x = play.GetCoordinateX(0); int y = play.GetCoordinateY(0); if (isVerticalPlay) { int topOfWord = y; int midX = x; StringBuilder wordBuilder = new StringBuilder(); // Get to the top of the vertical word. while (topOfWord > 0) { if (this.boardGrid[x, topOfWord - 1].IsEmpty()) { break; } else { --topOfWord; } } while (topOfWord <= 14) { if (this.boardGrid[x, topOfWord].IsEmpty()) { break; } else { wordBuilder.Append(this.boardGrid[x, topOfWord].ContainedLetterTile.LetterValue); ++topOfWord; } } if (wordBuilder.ToString().Length > 1) { words.Add(wordBuilder.ToString()); } wordBuilder.Clear(); // Get all the words that branch off from that word. for (int i = 0; i < play.GetParallelListLength(); ++i) { int leftOfWord = play.GetCoordinateX(i); // Go to the left end of the word while (leftOfWord > 0) { if (this.boardGrid[leftOfWord - 1, play.GetCoordinateY(i)].IsEmpty()) { break; } else { --leftOfWord; } } // Read rightward until the word ends. while (leftOfWord <= 14) { if (this.boardGrid[leftOfWord, play.GetCoordinateY(i)].IsEmpty()) { break; } else { wordBuilder.Append(this.boardGrid[leftOfWord, play.GetCoordinateY(i)].ContainedLetterTile.LetterValue); ++leftOfWord; } } if (wordBuilder.ToString().Length > 1) { words.Add(wordBuilder.ToString()); } wordBuilder.Clear(); } } else { int leftOfWord = x; int midY = y; StringBuilder wordBuilder = new StringBuilder(); // Get to the top of the vertical word. while (leftOfWord > 0) { if (this.boardGrid[leftOfWord - 1, y].IsEmpty()) { break; } else { --leftOfWord; } } while (leftOfWord <= 14) { if (this.boardGrid[leftOfWord, y].IsEmpty()) { break; } else { wordBuilder.Append(this.boardGrid[leftOfWord, y].ContainedLetterTile.LetterValue); ++leftOfWord; } } if (wordBuilder.ToString().Length > 1) { words.Add(wordBuilder.ToString()); } wordBuilder.Clear(); // Get all the words that branch off from that word. for (int i = 0; i < play.GetParallelListLength(); ++i) { int topOfWord = play.GetCoordinateY(i); // Go to the left end of the word while (topOfWord > 0) { if (this.boardGrid[play.GetCoordinateX(i), topOfWord - 1].IsEmpty()) { break; } else { --topOfWord; } } // Read rightward until the word ends. while (topOfWord <= 14) { if (this.boardGrid[play.GetCoordinateX(i), topOfWord].IsEmpty()) { break; } else { wordBuilder.Append(this.boardGrid[play.GetCoordinateX(i), topOfWord].ContainedLetterTile.LetterValue); ++topOfWord; } } if (wordBuilder.ToString().Length > 1) { words.Add(wordBuilder.ToString()); } wordBuilder.Clear(); } } return words; }