Tic Tac Toe
Requirements
A simple Tic Tac Toe game for two players.
A 3x3 board where players alternately place their pieces (
X
orO
).The game ends when:
A player gets 3 of their pieces in a row, column, or diagonal.
The board is full, resulting in a draw.
Class Diagram
+------------------+
| Player |
+------------------+
| - name: String |
| - piece: PieceType|
+------------------+
| + getName(): String |
| + getPiece(): PieceType|
+------------------+
+------------------+
| PlayingPiece |
+------------------+
| - type: PieceType|
+------------------+
| + getType(): PieceType|
+------------------+
+------------------+
| PlayingPieceO |
+------------------+
| - type: O |
+------------------+
| + getType(): PieceType|
+------------------+
+------------------+
| PlayingPieceX |
+------------------+
| - type: X |
+------------------+
| + getType(): PieceType|
+------------------+
+------------------+
| Board |
+------------------+
| - grid: PieceType[][]|
+------------------+
| + placePiece(row: int, col: int, piece: PlayingPiece): boolean|
| + isFull(): boolean|
| + display(): void|
| + checkWin(row: int, col: int, piece: PieceType): boolean|
+------------------+
+------------------+
| Game |
+------------------+
| - board: Board |
| - players: Player[]|
| - currentPlayer: int|
+------------------+
| + play(): void |
| + switchPlayer(): void|
+------------------+
Implementation
1. Enum: PieceType
Defines the type of pieces (X
, O
, or EMPTY
).
public enum PieceType {
X,
O,
EMPTY
}
2. Abstract Class: PlayingPiece
Represents a generic playing piece.
public abstract class PlayingPiece {
protected PieceType type;
public PieceType getType() {
return type;
}
}
3. Concrete Classes: PlayingPieceO and PlayingPieceX
Define specific implementations for X
and O
.
public class PlayingPieceO extends PlayingPiece {
public PlayingPieceO() {
this.type = PieceType.O;
}
}
public class PlayingPieceX extends PlayingPiece {
public PlayingPieceX() {
this.type = PieceType.X;
}
}
4. Player Class
Represents a player with a name and their associated piece.
public class Player {
private String name;
private PieceType piece;
public Player(String name, PieceType piece) {
this.name = name;
this.piece = piece;
}
public String getName() {
return name;
}
public PieceType getPiece() {
return piece;
}
}
5. Board Class
Handles the game board and its operations.
public class Board {
private PieceType[][] grid;
public Board() {
grid = new PieceType[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
grid[i][j] = PieceType.EMPTY;
}
}
}
public boolean placePiece(int row, int col, PlayingPiece piece) {
if (row < 0 || row >= 3 || col < 0 || col >= 3 || grid[row][col] != PieceType.EMPTY) {
return false;
}
grid[row][col] = piece.getType();
return true;
}
public boolean isFull() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (grid[i][j] == PieceType.EMPTY) {
return false;
}
}
}
return true;
}
public boolean checkWin(int row, int col, PieceType piece) {
// Check row
if (grid[row][0] == piece && grid[row][1] == piece && grid[row][2] == piece) {
return true;
}
// Check column
if (grid[0][col] == piece && grid[1][col] == piece && grid[2][col] == piece) {
return true;
}
// Check diagonals
if (row == col && grid[0][0] == piece && grid[1][1] == piece && grid[2][2] == piece) {
return true;
}
if (row + col == 2 && grid[0][2] == piece && grid[1][1] == piece && grid[2][0] == piece) {
return true;
}
return false;
}
public void display() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(grid[i][j] + " ");
}
System.out.println();
}
}
}
6. Game Class
Manages the overall gameplay and switching turns.
import java.util.Scanner;
public class Game {
private Board board;
private Player[] players;
private int currentPlayer;
public Game(Player player1, Player player2) {
this.board = new Board();
this.players = new Player[]{player1, player2};
this.currentPlayer = 0;
}
public void play() {
Scanner scanner = new Scanner(System.in);
while (true) {
board.display();
Player player = players[currentPlayer];
System.out.println(player.getName() + "'s turn (" + player.getPiece() + ")");
System.out.println("Enter row and column (0, 1, 2):");
int row = scanner.nextInt();
int col = scanner.nextInt();
if (!board.placePiece(row, col, createPlayingPiece(player.getPiece()))) {
System.out.println("Invalid move. Try again.");
continue;
}
if (board.checkWin(row, col, player.getPiece())) {
board.display();
System.out.println(player.getName() + " wins!");
break;
}
if (board.isFull()) {
board.display();
System.out.println("The game is a draw!");
break;
}
switchPlayer();
}
scanner.close();
}
private void switchPlayer() {
currentPlayer = (currentPlayer + 1) % 2;
}
private PlayingPiece createPlayingPiece(PieceType type) {
return type == PieceType.X ? new PlayingPieceX() : new PlayingPieceO();
}
}
7. Main Class
The entry point for the application.
public class Main {
public static void main(String[] args) {
Player player1 = new Player("Alice", PieceType.X);
Player player2 = new Player("Bob", PieceType.O);
Game game = new Game(player1, player2);
game.play();
}
}
Execution Flow
Start: The game initializes with a 3x3 board and two players.
Gameplay:
Each player takes turns placing their piece on the board.
The system validates moves and checks for a win or draw after every move.
End:
A player wins if they align three of their pieces.
The game ends in a draw if the board is full with no winner.
Output Example
Game Starts:
EMPTY EMPTY EMPTY
EMPTY EMPTY EMPTY
EMPTY EMPTY EMPTY
Alice's turn (X)
Enter row and column (0, 1, 2):
0 0
Winning Condition:
X X X
EMPTY EMPTY EMPTY
O O EMPTY
Alice wins!
Draw Condition:
X O X
X O O
O X O
The game is a draw!
Last updated