This project is a java version of the board game, Scrabble. For more information on Scrabble and/or to see the rules, visit the wiki or the Scrabble Website. The game is played on a 15x15 board, is compatible with 2-4 players and uses this list of words as a dictionary by default.
π₯ Amin Zeina (101186297)
π₯ Michael Kyrollos (101183521)
π₯ Pathum Danthanarayana (101181411)
π₯ Yehan De Silva (101185388)
Button | Description |
---|---|
Play | Play tile one by one on to the board. Click "Submit" once finished. |
Redraw | Select all the tiles on player's rack that they wish to redraw. Returns them to the tile bag and redraws new tiles. |
Skip | Skips player's turn and starts the next player's turn |
Menu Item | Description |
---|---|
Undo | Go back to the start of the previous player's turn |
Redo | Return to current turn if an "undo" was made |
Save Game | Save the current game to be resumed later |
Load Game | Load an existing game to resume playing |
Quit | End the game and display winner and player scores |
Blue squares - x2 letter square - Doubles the value of the letter placed on this square
Green squares - x3 letter square - Triples the value of the letter placed on this square
Red squares - x2 word square - Doubles the value of the word placed on this square
Orange squares - x3 word square - Triples the value of the word placed on this square
Delegation was used to ensure each class performs its rightful responsibilities and have high cohesion.
Linear control flow between classes was preferred when coding. For example, when placing a word, the game validates the word in the dictionary and then delegates to player to continue placing the word. The player can than validate if they have the correct tiles and pass them along to the board to place.
High encapsulation to increase security/privacy of code and decrease tight coupling.
Used public constants for fields to make them immutable, but still accessible to the rest of the program.
Text-file used instead of API for dictionary as API usage was limited and some APIs were missing needed operations.
Model-View-Controller used as it provides a way to get user-input, pass it on to the model to process and then update the view.
Premium square implemented as subclasses of Square to easily distinguish premium squares and to avoid code duplication
For the AI: Overall Architecture:
The AI logic is abstracted from the rest of the game. There is a suite of classes dedicated for the AI: AIBoard, AI, AIPlayerModel, LetterTree. The current AI implementation is based off of the findings of a research paper known as The World's Fastest Scrabble Game which outlines data structures and architecture necessary to achieve a high speed logic.
How the AI Achieves High Efficiency
The algorithm begins its search from the anchor squares (squares that are adjacent to tiles already on the board) which will guarantee that the word created is adjacent to another tile. If the word search was done right away, there would be many moves created where the AI would fail to connect the partial word to tiles on the board
The Suite of classes needed to achieve it
AIPlayerModel.java
: This class implements the ScrabblePlayer interface, allowing all players (AI or human) to be interpreted at the same level (necessary when adding points, creating a rack, etc.) and stored in the same list. The AIPlayerModel
class is necessary for the encapsulation of the extra computation necessary to mimic a ScrabblePlayer
. Since the AI will also be using many PlayerModel.java
methods, it will be extending this class and using some relevant methods (i.e. playWord()
). The class is responsible for handling a new move created by the AI, known as an AIMove
-> this is a subclass of AI.java
. The AIPlayerModel
will be responsible for converting the AIMove
to a PlayWordEvent which is a format understandable by the PlayerModel
. AI.java
: This class contains all the logic for the necessary to create a Scrabble move. It scans the board and uses its own rack to create ALL possible moves, given the circumstances. It will return an AIBoard
for each move which represents what the board will reassemble once the AI makes that move. The AI logic will also iterate through all the moves that it has created and will return the highest scoring one, creating an AIMove
which can then be processed by the AIPlayerModel
AIBoard.java
: This class models uses a copy of the BoardModel in a char[][] format. This allows all calculations that the AI makes to be done on primitive data types (char), vastly simplifying the logic code in AI.java
.LetterTree.java
: This class uses a text file containing a list of words that can be used to create the dictionary. This dictionary uses the tree-node structure specifically implemented for the use-cases of the AI. This prevents access issues to ScrabbleDictionary.java
.
Notes about the AI
CustomBoardHandler, a subclass of org.xml.sax.helpers.DefaultHandler, used to handle XML parsing for custom boards
Data Structure | Use |
---|---|
DictionaryNode | A dictionary node contains a boolean flag called terminal and an array of DictionaryNodes. A word is created by going down the data structure and adding each letter at the correct spot in the array. This ensures that common operations such as adding a new word or searching for a word is O(n) where n depends on the length of the word, and not the length of the dictionary. |
2D array of Square Objects | Easy to represent and access individual squares on the scrabble board. |
RackModel | Used to store the list of tiles a player currently has in their hand. |
JButtons | Used to extend Tile and Square classes as tiles and squares should now be clickable in the GUI |
Tile | Ties together a letter and point value for all tiles in the Scrabble game. |
BlankTile | Subclass of Tile - represents a blank tile, which has a customizable letter |
TileBag | An ArrayList containing all the tiles of the game. |
Square | Subclass of JButton - used to represent a square on the board, which holds a tile |
LetterPremiumSquare | Subclass of Square - used to represent a premium square which doubles the letter value of the tile placed on it |
WordPremiumSquare | Subclass of Square - used to represent a premium square which doubles the word value of the tiles placed on it |
Hashmaps | Used to map frequency values (Character-Integer) and point values (Integer-ArrayList of chars) for all the tiles in a TileBag |
Stack | Used to implement the undo/redo feature. Because undoing/redoing is going back to the last turn (LIFO), a stack is a good way of implementing LIFO. |
XML | Used as a method to store information regarding premium squares. It can be parsed by an XML parser to extract the locations of all premium squares. |
Ensure you have selected all tiles that are part of your word, including tiles that have already been placed on the board. Selected tiles are highlighted with a white border. See below for the proper play of the word "ten" using the existing "t" on the board.
<board>
<doubleLetterSquares>
<!--Enter coordinates for double letter squares here-->
<coord>0,0</coord>
</doubleLetterSquares>
<tripleLetterSquares>
<!--Enter coordinates for triple letter squares here-->
<coord>1,0</coord>
<coord>1,2</coord>
</tripleLetterSquares>
<doubleWordSquares>
<!--Enter coordinates for double word squares here-->
<coord>2,0</coord>
<coord>2,1</coord>
<coord>2,2</coord>
</doubleWordSquares>
<tripleWordSquares>
<!--Enter coordinates for triple word squares here-->
<coord>3,0</coord>
<coord>3,1</coord>
<coord>3,2</coord>
</tripleWordSquares>
</board>