For one of my assignments in Object-Oriented Programming, I was tasked with programming a game called Reversi. Reversi is a multi-player game where users are represented by either a black (represented by Kirby in our version) or white (Meta Knight) disc; both compete against each other and aim to flip as many of the opponent's discs as possible. Whoever has the most number of discs on their side wins the game. A standard game of Reversi employs a square-shaped board, but for our assignment, we were instructed to design a hexagonal version of Reversi. We used a Model View Controller approach when designing our program.
There are four types of AI players in our game, each implementing different strategies to beat the opponent (e.g., one AI strategy is to capture as many discs as possible; another strategy is to prevent the opponent's next move). In the video to the left, the first player (Kirby) is a human player, competing against the second AI player (Meta Knight) whose strategy is to capture as many discs as possible. Users can choose whether they want the AI player to be Kirby or Meta Knight.. or even better, AI vs. AI.
In this version of Reversi, users can choose to play with a square-shaped board rather than a hexagonal board. Implementing this feature was fairly simple as we had been abstracting our design appropriately and there were no unnecessary coupling between our actual board and the rules of the game. As such, all features (including the AI players) from our hexagonal version worked with our square version as well.
If the user presses on the 'H' key, they can activate hints on their window of the game. When activating this hint and selecting on a particular cell, this hint tells the user how many discs of the opponent's they would be flipping if they were to make a move on that disc. Hints can be deactivated the same way they were activated.
As an extension of this assignment, we received code from our providers. Their provided code included their view and strategy implementations. Using mock classes, we integrated their view to our model and controller.
This process of customizing our interface was not simple. Not only were we navigating how to use Java's Swing library, but we also faced various difficulties with having our custom images compile during run-time. I attended office-hours consecutively and even had to schedule time with my professor outside of their office hours to make this work. Eventually, we had to implement fall-back methods and learn how to use a resource directory. The left picture is the view we were originally provided in the assignment spec.
For one of our first projects in Object-Oriented Programming, we designed Klondike (also known as Solitaire), a popular single-player card game played with a standard 52-card deck. The objective is to build four foundation piles in ascending order from Ace to King, with each pile representing one suit.
This assignment required implementing the Model-View-Controller (MVC) design pattern. The view displays a textual representation showing the piles, current score, and the first card of the draw pile. Users interact with the game through textual commands sent to the controller, which updates the model accordingly.
The classic version with standard rules: build foundation piles in ascending order by suit, and cascade piles in descending order with alternating colors.
A variant with modified rules: valid runs consist of cards of the same color (rather than alternating colors), and when moving multiple cards across cascade piles, the build must consist of the same suit.
This version introduces a strategic constraint: players have a limited number of redraws allowed for the draw card, adding an extra layer of difficulty and requiring more careful planning.
To avoid redundant code, I abstracted the basic rules of Klondike that apply across all three variants into an abstract base class. Each variant (Basic, Whitehead, and Limited Draw) extends this abstract class, inheriting common functionality while implementing their specific rule variations. This design demonstrates proper object-oriented principles including inheritance, polymorphism, and the DRY (Don't Repeat Yourself) principle.