Object-Oriented Design for Othello (Reversi)
Problem
Othello is played as follows: Each Othello piece is white on one side and black on the other. When a piece is surrounded by its opponents on both the left and right sides, or both the top and bottom, it is said to be captured and its color is flipped. On your turn, you must capture at least one of your opponent’s pieces. The game ends when either user has no more valid moves, and the win is assigned to the person with the most pieces. Implement the object oriented design for Othello.
Solution
The game flow looks like this:
- Initialize the game which will be done by constructor
- Get first user input
- Validate the input
- Change board configuration
- Check if someone has won the game Get second user input
- Validate the input
- Change the board configuration
- Check if someone has won the game
Understanding the classes Player There will be 2 players - black and white. The players will have the label with them - whether they are black or white, and set of pieces. The pieces can be added or removed from the set.
Board Board will consists of 2 players, and set of pieces.
public class Player {
private final char label;
private Set<Pair<Integer>> pieces = new HashSet<Pair<Integer>>();
public Player(char label) {
this.label = label;
}
public void addOnePiece(Pair<Integer> piece) {
pieces.add(piece);
}
public void removeOnePiece(Pair<Integer> piece) {
pieces.remove(piece);
}
public Set<Pair<Integer>> getPieces() {
return pieces;
}
public char getLabel() {
return label;
}
}
public class Board {
private final char BLACK = '*';
private final char WHITE = '^';
private Player black;
private Player white;
private char[][] board = new char[8][8];
public Board() {
## Problem
Othello (Reversi) is a two-player board game played on an 8x8 grid. Each piece has a black side and a white side. When a player places a piece such that one or more of the opponent's pieces are bounded in a straight line (horizontal, vertical or diagonal) between the new piece and another of the player's pieces, those opponent pieces are flipped. On your turn you must capture at least one opponent piece. The game ends when neither player has a valid move; the player with the most pieces wins. Implement an object-oriented design for Othello.

## Solution
### 1. Requirements Analysis
Functional requirements:
- Represent the game board (8x8) and pieces (black/white).
- Allow two players to alternate turns and place pieces.
- Validate moves according to Othello rules (a move must flip at least one opponent piece).
- Flip the captured pieces when a valid move is played.
- Detect end-of-game and compute the winner by piece counts.
- Provide a simple I/O loop or API to read moves and display the board.
Non-functional requirements:
- Correctness: move validation and flipping must follow the rules precisely.
- Simplicity and testability: clear separation between model (Board, Player) and I/O.
- Extensibility: allow adding an AI player or alternate board sizes in the future.
Edge cases and constraints (inferred from source):
- Input validation for coordinates and bounds.
- Handling no-valid-move cases for a player (skip turn) and game termination when both players have no moves.
### 2. Use Case Diagram
Actors: Player (human or AI), Game Controller
Use case summary: Players start a game, make moves (place piece), view board, and end the game when no moves remain.
```mermaid
graph TD
subgraph Othello Game
UC1(Start Game)
UC2(Make Move)
UC3(View Board)
UC4(End Game)
end
Player --> UC2
Player --> UC3
GameController --> UC1
GameController --> UC4
3. Class Diagram
Core classes and responsibilities (derived from the original Java example):
- Player: holds label/color and set of pieces (positions) owned by the player.
- Board: maintains the 8x8 grid, validates moves, flips pieces, and provides board state.
- GameController (or Game): coordinates turns, input/output, and end-of-game detection.
- Pair / Position: small value object representing (row, col).
classDiagram class Player { +char label +Set~Position~ pieces +addOnePiece(Position) +removeOnePiece(Position) } class Board { +char[][] grid +Player black +Player white +boolean checkMove(Player, Player, Position) +void flip(Position) +boolean capturedLeftAndRight(Position) +boolean capturedUpAndDown(Position) } class GameController { +Board board +void start() +void step() } Player "1" -- "*" Position : owns GameController "1" -- "1" Board
4. Activity Diagrams
Activity: Making a Move
graph TD A[Player inputs coordinates] --> B[Validate input bounds] B --> C{Is move valid?} C -- Yes --> D[Place piece and flip captured pieces] C -- No --> E[Reject move and ask for input] D --> F[Update player's piece set]
Activity: Game Loop
graph TD S[Start game] --> T[Initialize board and players] T --> Turn[While either player has valid moves] Turn --> PlayerMove[Current player makes a move or passes] PlayerMove --> Check[Check and flip pieces] Check --> Switch[Switch turn] Switch --> Turn Turn --> End[Compute winner and end game]
5. High-Level Code Implementation
Below are cleaned skeletons adapted from the original Java implementation and a Python equivalent. These include key classes, attributes, and method signatures only.
Java
public class Position {
private final int row;
private final int col;
public Position(int row, int col) { this.row = row; this.col = col; }
public int getRow() { return row; }
public int getCol() { return col; }
}
public class Player {
private final char label;
private Set<Position> pieces = new HashSet<>();
public Player(char label) { this.label = label; }
public void addOnePiece(Position p) { pieces.add(p); }
public void removeOnePiece(Position p) { pieces.remove(p); }
public Set<Position> getPieces() { return pieces; }
public char getLabel() { return label; }
}
public class Board {
private final char BLACK = '*';
private final char WHITE = '^';
private Player black;
private Player white;
private char[][] grid = new char[8][8];
public Board() { /* initialize grid and starting pieces */ }
public boolean checkMove(Player player, Player opponent, Position pos) {
// validate bounds and flipping rules
return false;
}
public boolean capturedLeftAndRight(Position pos) { return false; }
public boolean capturedUpAndDown(Position pos) { return false; }
public void flip(Position pos) { /* flip piece at pos */ }
}
public class GameController {
private Board board;
public void start() { /* game loop */ }
}
Python
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Set
@dataclass(frozen=True)
class Position:
row: int
col: int
@dataclass
class Player:
label: str
pieces: Set[Position] = field(default_factory=set)
def add_one_piece(self, p: Position) -> None:
self.pieces.add(p)
def remove_one_piece(self, p: Position) -> None:
self.pieces.discard(p)
class Board:
def __init__(self) -> None:
self.black = Player('*')
self.white = Player('^')
self.grid: list[list[str]] = [['.' for _ in range(8)] for _ in range(8)]
def check_move(self, player: Player, opponent: Player, pos: Position) -> bool:
raise NotImplementedError
def flip(self, pos: Position) -> None:
raise NotImplementedError
class GameController:
def __init__(self) -> None:
self.board = Board()
def start(self) -> None:
# main loop handling turns
raise NotImplementedError
References
- Playable Java version: http://www.halygames.com/portfolio/othello/
- Heuristic discussion for Reversi/Othello: https://kartikkukreja.wordpress.com/2013/03/30/heuristic-function-for-reversiothello/