Scrambled Words Game

Projects

Since this is a final course project, some guidelines were provided via a requirements document, making them mandatory. Among these, three stood out, bringing an unprecedented level of difficulty to the project:

  1. Running the application in the console

    Undoubtedly, the most emblematic requirement. After an initial evaluation lasting 5 hours and 30 minutes (design phase), it was necessary to choose between:

    • Developing the application for the console — adding an unimaginable level of complexity to the project.
    • Developing the application with the Java Swing Library — without adding any complexity to the project.

    Given these options, I chose to follow the original requirements document and develop the application for the console — the only way to truly practice and consolidate some of the concepts covered in the course (such as CRC modeling).

    In total, 266 hours were spent solely on CRC modeling — to define the classes, their responsibilities, and dependencies. After that, an additional 73 hours were needed to build the UML class diagram.

    During this entire time, I applied the software engineering principles of Tell Don't Ask and The Law of Demeter to reduce coupling between classes.

  2. Building an application where parts of its execution can be easily swapped

    To meet this requirement, the Factory design pattern was applied twice:

    • Factory Pattern 1: The application has an abstract class called Scrambler (Embaralhador). The Scrambler class has three implementations, each using a different technique to scramble words.
    • To allow a Scrambler instance to be easily added or removed from the application, the task of instantiating them is delegated to the ScramblerFactory class (FabricaEmbaralhador). In this way, to add or remove a Scrambler, you only need to modify one class: ScramblerFactory.

    • Factory Pattern 2: The application has an abstract class called GameMechanics (MecanicaDoJogo). The GameMechanics class has three implementations, each presenting a different sequence of steps to conduct and end the match.
    • To allow a GameMechanics instance to be easily added or removed from the application, the task of instantiating them is delegated to the GameMechanicsFactory class (FabricaMecanicaDoJogo). In this way, to add or remove a GameMechanics, you only need to modify one class: GameMechanicsFactory.

  3. Only a single class can read user input and print information to the console

    To meet this requirement, inheritance and polymorphism were used.

    The Scrambled Words Game has 16 screens — each instantiated by a different class. Every screen needs to print and read information from the console, since that is their core function.

    To solve this challenge, an abstract class called NavigationScreen (TelaNav) was created. The NavigationScreen class contains the readInput method (leEntrada), which prints the game screen to the console and reads user input through a Scanner attribute.

    The next step was to use inheritance to make all 16 game screens subclasses of NavigationScreen (by extending it). This way, every screen can read and print information to the console by inheriting the readInput method from the superclass. At the same time, thanks to polymorphism, every class that extends NavigationScreen is considered a NavigationScreen. Therefore, we can say that only one class reads from and prints to the console: NavigationScreen.