Design

Please see Javadoc for component API documentation.

Categories of Components

For better organization, the components are divided into the following categories:

  • Core
  • GUI
  • Utils

Core Logic

Core logic is the rules and logic of the mastermind game, e.g., how hints are provided, how guesses are validated, etc.

Core Components

Core components are responsible for the core logic of the program, e.g., solving the mastermind puzzle. It includes components closely tied to the program’s logic, and would not be reusable by any other program.

Core components may depend on other core components and utils, and not GUI components.

GUI Components

GUI components are responsible for the user interface of the program. It includes scenes and panels, where scenes are stages of the game, and panels are common GUI components that can be shared across scenes.

GUI components may depend on both core components and utils.

Utility Components

Utility components are components that don’t fit as either core or GUI, i.e., they are general-purpose components that are not coupled with the program logic.

For example, Log and ANSIColor are utility components, since although the program depend on them, they are not part of the core logic nor the GUI.

Utility components may only depend on other utility components, but not core or GUI.

Communications Between Core and GUI Components

Algorithmic Solvers ↔ GUI

sequenceDiagram
  gui ->> solver: queries first guess (without hints)
  solver -->> gui: returns first guess
  gui ->> solver: queries subsequent guesses (with hints)
  solver -->> gui: returns subsequent guesses

Human Solver ↔ GUI

sequenceDiagram
  gui ->> solver: submits user guesses
  solver -->> gui: validates and returns hints

Single Responsibility Principle

For the ease of unit testing and maintainability, each class and function should serve a single purpose.

All components are designed to adhere to the Single Responsibility Principle.

Separation of Data and Logic

Some components may require loading of external data, e.g., predefined secret codes for code maker mode, as opposed to pseudo-random generation.

To allow modification to data without changing the source code, data is stored separately and dynamically loaded at runtime.

Use of Enumerators

Type safety is ensured by using enumerators to represent constants, e.g., colors, log severity levels, etc.

Design Patterns

Various design patterns are employed where appropriate.

For example, singleton for Log and dependency injection for CodeBreaker.