0

I am working on a CLI chess game that only involves 2 human players, I decided to make it follow the MVC architecture to ensure separation of concern and to make the possibility of a GUI/web integration easier to achieve.

Here is the package diagram:

enter image description here

The view only has the View class that draws the board and the pieces, the controller takes input from the user and communicates with the Game class inside of the game package, which is more of a Facade class, which is inside the model.

The player can enter a command (i.e "move a2 a4") and the controller will pass that to the game object and execute the command using the command design pattern.

ChessGame (controller) class:

package controller;

import model.game.Game;
import view.View;

import java.util.Scanner;

public class ChessGame {
    private final Game game;
    private final View view;
    public ChessGame() {
        this.game = new Game();
        this.view = new View();
    }

    public void start() {
        Scanner sc = new Scanner(System.in);
        view.draw(game.getBoard());
        initializePlayers(sc);
        while (true) {
            try {
                System.out.println(game.getCurrentPlayer() + " turn!");
                if (game.playerIsInCheck()) {
                    System.out.println("Check! Protect the king.");
                }
                System.out.println("Enter a command:");
                game.executeCommand(sc.nextLine());
                if (game.pawnPromoted()) {
                    handlePromotion(sc);
                }
                //If player is still in check after executing the move, undo the move.
                if (game.playerIsInCheck()) {
                    game.undoCommand();
                    throw new IllegalArgumentException("King is still in check, undoing last move...");
                }
                view.draw(game.getBoard());
            } catch (Exception e) {
                System.out.println(e.getMessage());
                System.out.println("Try again.");
                continue;
            }
            game.setWhitePlayerTurn(!game.isWhitePlayerTurn());
            game.setBlackPlayerTurn(!game.isBlackPlayerTurn());
        }
    }
    public void handlePromotion(Scanner sc) {
        System.out.println("PROMOTION!");
        System.out.println("Choose a piece to promote to:");
        System.out.println("1)Queen\n2)Rook\n3)Bishop\n4)Knight");
        int choice = sc.nextInt();
        game.promote(choice);
    }
    private void initializePlayers(Scanner sc) {
        System.out.println("Enter white player name: ");
        String whitePlayerName = sc.nextLine();
        System.out.println("Enter black player name: ");
        String blackPlayerName = sc.nextLine();
        game.setWhitePlayerName(whitePlayerName);
        game.setBlackPlayerName(blackPlayerName);
    }
}

draw method inside of View:

    public void draw(Board board) {
    int rows = Board.ROWS;
    int columns = Board.COLUMNS;
    String borderColor = ANSI_RED;
    System.out.println(borderColor + "   ===================" + ANSI_RESET);
    for (int i = 1; i <= columns; i++) {
        System.out.print(((columns + 1) - i) + borderColor + " || " + ANSI_RESET);
        for (int j = 1; j <= rows; j++) {
            Square currentSquare = new Square(j, (columns + 1) - i);
            if (board.isSquareOccupied(currentSquare)) {
                printPiece(board.getPieceFromSquare(currentSquare));
            } else {
                System.out.print("- " + ANSI_RESET);
            }
        }
        System.out.println(borderColor + "||" + ANSI_RESET);
    }
    System.out.println(borderColor + "   ===================" + ANSI_RESET);
    System.out.println("\t a b c d e f g h");
}

ANSI_* are constant variables for color.

I am not going to add code from the model since I am concerned about the architecture and the way the classes communicate, not the logic.

Is this overengineered, or still a sensible design choice for a CLI application? Also, since we're using DI in draw to insert the board, does this make the view package dependent on model? Is there a way to use draw without any DI?

11
  • 2
    Asking if this is overkill will attract opinionated answers, which doesn't fit the format of this community. Is there a specific problem you have with this design? Aug 20, 2022 at 22:45
  • The way you drew the model makes no sense with view and controller being empty. All you have is in model now. It seems to me Board is your view and pieces are just an internal detail to board. Game is your model, controller takes input from the user and forwards it to game. Whether your application classifies as CLI or GUI or web is irrelevant. CLI does not make it "simple". Aug 21, 2022 at 8:22
  • 1
    Actually MVC can be done very simply. A good example is Money. Controller is the interface through which you manipulate its value. Model stores the value. View puts the dollar sign and decimal on it. It doesn’t have to be a framework for GUIs. Aug 21, 2022 at 18:50
  • 1
    @ThorbjørnRavnAndersen nah, it’s only about having three places focused on three responsibilities. That’s all MVC is. Anything more then that is just people playing monkey see monkey do and using the name MVC to justify it. Aug 21, 2022 at 20:51
  • 1
    @RobertHarvey MVC is pointless without a view but the view does not have to be a pixel or vector based GUI. A chess board can be perfectly rendered on a character terminal using dashes, pipe characters, plusses and letters. A class that converts a board state to an output string can be considered a view. Aug 21, 2022 at 21:19

2 Answers 2

3

MVC still makes sense for a CLI (command line interface).

However what went wrong is the I/O took over board and pieces and commands.

Instead you should have an abstracted Model of board and pieces. And your View should have a PieceView using System.out.print, and so on. Commands are also reflected in View as System.in.

Consider that the View (and Input) layer could in a second generation be implemented with JavaFX. Separate packages for M, V, and C.

Also cumbersome might be that View holds state, model information. Like a clickable check box. Here you only have line input, with some parsing. The Controller specifies the events, actions, commands. The input line parsing ("View") and dispatch to controller is something for the View.

In this way CLI might be replaced in some far future, with JavaFX, or with an Android GUI. System.in and System.out (and maybe System.console) held separate.

The other merit is, that you can concentrate on abstract things: incorporate game logic without going down to implementing all in CLI. Just define a Controller event/action, handle it abstractly, and later give it an implementation. The code design is more readable, not sinking into details.

Not necessarily MVC is the solution of all software writing. One can write a game as integrated logical rules, as a mechanical machine. But MVC is a good start structuring thins.

0

MVC can be a sensible design choice for a CLI application. Whether it is entirely depends on your requirements.

You state the following requirement: "to make the possibility of a GUI/web integration easier" as the justification for MVC.

MVC is a Design Pattern

The concept of Design Pattern has been coined by the Gang of Four almost 30 years ago. A design pattern is described by a number of properties, like Motivation, Applicability, Tradeoffs and more.

To answer the question, you should consult a good MVP Pattern description and check your requirements against the benefits and tradeoffs. You should also investigate related patterns to find and evaluate alternatives.

MVC Trade-Offs

MVC is useful if you have more than one view and/or controller. In addition, if you want to be able to add and remove views and controllers at runtime, MVC is a good choice.

These benefits come at the expense of added complexity.

MVC for Your Application (CLI Chess Game)

From the little I see here, it is unlikely that using MVP is worth your while: You can simply use a good (Java) Interface to allow the connection of additional views. And you have always 2 players, therefore 2 controllers.

I would recommend you to elaborate on "to make the possibility of a GUI/web integration easier": How exactly? What scenarios do you envision? Write it down, sketch out an architecture.

If you do this as a learning exercise, then of course this could be a great project for better understanding design patterns in general and MVP in particular.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.