Related Articles

Low Level Design of Tic Tac Toe | System Design

In classic games, few are as universally recognized and enjoyed as Tic Tac Toe. Despite its apparent simplicity, this game engages players of all ages in a battle of wits and strategy. In this article, we delve into the intricacies of designing a low-level structure for Tic Tac Toe that captures the essence of the game and highlights the underlying complexities.

The Essence of Tic Tac Toe

Tic Tac Toe, known colloquially as “Xs and Os,” is a two-player game typically played on a 3×3 grid. The objective is simple: be the first to form a horizontal, vertical, or diagonal line of three of your marks (either “X” or “O”). The elegance of the game lies in its deceptive complexity, while the rules are straightforward, devising an unbeatable strategy demands a keen understanding of the game’s dynamics.

Rules of the game

Firstly let’s understand the rules of the game:

• Setup: The game is played on a 3 * 3 grid. One player uses ‘X’ another player uses ‘O’ and each player takes turns making their moves.
• Winner: The game is won by the player placing his or her symbol in a row, column, or diagonal. The first player to get three symbols in a row wins the game. When the player reaches this, the game ends immediately.
• Draw: If all the grid cells are filled and no player has three symbols in a row, the game will be a tie or a draw.
• Illegal Moves: A player cannot place his or her symbol on a tile occupied by an opponent’s symbol or their own symbol. The move must be made to an empty cell.

Representing the Game Board

At the heart of every game lies the game board. In our low-level design for Tic Tac Toe, we choose a 2D array or matrix to represent the board. Each cell of the array can take three possible values: empty, “X,” or “O.” This array forms the canvas upon which players will make their moves.

Python3

 `# Initialize an empty 3x3 Tic Tac Toe board``board ``=` `[[``' '` `for` `_ ``in` `range``(``3``)] ``for` `_ ``in` `range``(``3``)]`

Player Turns and Moves

In any game, managing player turns is crucial. We can represent the players using simple integers â€“ player 1 and player 2. Their moves are translated to row and column indices on the game board.

Python3

 `current_player ``=` `1`  `# Player 1 starts` `row ``=` `1``column ``=` `2` `# Placing the current player's mark on the board``board[row][column] ``=` `'X'` `if` `current_player ``=``=` `1` `else` `'O'`

Validating Moves

Ensuring that players adhere to the rules is paramount. The low-level design includes a move validation process, verifying that the chosen cell is empty and within the bounds of the board.

Python3

 `def` `is_valid_move(row, column):``    ``return` `0` `<``=` `row < ``3` `and` `0` `<``=` `column < ``3` `and` `board[row][column] ``=``=` `' '` `# Example usage``if` `is_valid_move(``1``, ``2``):``    ``# Perform the move``else``:``    ``print``("Invalid move. Please choose an empty cell within the board.")`

Determining the Winner

The climax of any Tic Tac Toe game is the declaration of a winner. Our low-level design accommodates a function to check for victory conditions after each move.

Python3

 `def` `check_winner(player):``    ``# Check rows, columns, and diagonals for three marks in a row``    ``# Return True if the player wins, False otherwise` `# Example usage``if` `check_winner(``1``):``    ``print``("Player ``1` `wins!")``elif` `check_winner(``2``):``    ``print``("Player ``2` `wins!")`

Tying It All Together

Tic Tac Toe’s low-level design is a harmonious interplay of game mechanics, data structures, and decision-making logic. From managing the game board to validating moves and determining victory, every element contributes to the immersive experience of the game.

So, the next time you engage in a friendly match of Tic Tac Toe, remember that behind the Xs and Os lies a thoughtfully crafted low-level design that brings a timeless game to life. As you strategize to outwit your opponent, you’re also experiencing the result of careful planning and design â€“ a testament to the enduring appeal of this classic pastime.

C++

 `#include ``#include ` `using` `namespace` `std;` `class` `TicTacToe {``private``:``    ``vector > board; ``// 3x3 game board``    ``int` `currentPlayer; ``// 1 for Player 1, 2 for Player 2` `public``:``    ``TicTacToe()``    ``{``        ``board = vector >(3,``                                      ``vector<``char``>(3, ``' '``));``        ``currentPlayer = 1;``    ``}` `    ``void` `printBoard()``    ``{``        ``for` `(``int` `i = 0; i < 3; ++i) {``            ``for` `(``int` `j = 0; j < 3; ++j) {``                ``cout << board[i][j];``                ``if` `(j < 2) {``                    ``cout << " | ";``                ``}``            ``}``            ``cout << endl;``            ``if` `(i < 2) {``                ``cout << "---------" << endl;``            ``}``        ``}``    ``}` `    ``bool` `isBoardFull()``    ``{``        ``for` `(``int` `i = 0; i < 3; ++i) {``            ``for` `(``int` `j = 0; j < 3; ++j) {``                ``if` `(board[i][j] == ``' '``) {``                    ``return` `false``;``                ``}``            ``}``        ``}``        ``return` `true``;``    ``}` `    ``bool` `makeMove(``int` `row, ``int` `column)``    ``{``        ``if` `(row < 0 || row >= 3 || column < 0 || column >= 3``            ``|| board[row][column] != ``' '``) {``            ``return` `false``; ``// Invalid move``        ``}``        ``board[row][column]``            ``= (currentPlayer == 1) ? ``'X'` `: ``'O'``;``        ``currentPlayer``            ``= 3 - currentPlayer; ``// Switch player (1 to 2 or``                                 ``// 2 to 1)``        ``return` `true``;``    ``}` `    ``bool` `checkWinner()``    ``{``        ``// Check rows, columns, and diagonals for a win``        ``for` `(``int` `i = 0; i < 3; ++i) {``            ``if` `(board[i][0] != ``' '``                ``&& board[i][0] == board[i][1]``                ``&& board[i][1] == board[i][2]) {``                ``return` `true``; ``// Row win``            ``}``            ``if` `(board[0][i] != ``' '``                ``&& board[0][i] == board[1][i]``                ``&& board[1][i] == board[2][i]) {``                ``return` `true``; ``// Column win``            ``}``        ``}``        ``if` `(board[0][0] != ``' '` `&& board[0][0] == board[1][1]``            ``&& board[1][1] == board[2][2]) {``            ``return` `true``; ``// Diagonal win``        ``}``        ``if` `(board[0][2] != ``' '` `&& board[0][2] == board[1][1]``            ``&& board[1][1] == board[2][0]) {``            ``return` `true``; ``// Diagonal win``        ``}``        ``return` `false``;``    ``}``};` `int` `main()``{``    ``TicTacToe game;``    ``int` `row, column;` `    ``while` `(!game.isBoardFull() && !game.checkWinner()) {``        ``game.printBoard();` `        ``cout << "Player " << game.getCurrentPlayer()``             ``<< ", enter your move (row and column): ";``        ``cin >> row >> column;` `        ``if` `(game.makeMove(row, column)) {``            ``cout << "Move successful!" << endl;``        ``}``        ``else` `{``            ``cout << "Invalid move. Try again." << endl;``        ``}``    ``}` `    ``game.printBoard();` `    ``if` `(game.checkWinner()) {``        ``cout << "Player " << (3 - game.getCurrentPlayer())``             ``<< " wins!" << endl;``    ``}``    ``else` `{``        ``cout << "It's a draw!" << endl;``    ``}` `    ``return` `0;``}`

Java

 `import` `java.util.Scanner;` `public` `class` `TicTacToe {``    ``private` `char``[][] board; ``// 3x3 game board``    ``private` `int``        ``currentPlayer; ``// 1 for Player 1, 2 for Player 2` `    ``public` `TicTacToe()``    ``{``        ``board = ``new` `char``[``3``][``3``];``        ``for` `(``int` `i = ``0``; i < ``3``; ++i) {``            ``for` `(``int` `j = ``0``; j < ``3``; ++j) {``                ``board[i][j] = ``' '``;``            ``}``        ``}``        ``currentPlayer = ``1``;``    ``}` `    ``public` `void` `printBoard()``    ``{``        ``for` `(``int` `i = ``0``; i < ``3``; ++i) {``            ``for` `(``int` `j = ``0``; j < ``3``; ++j) {``                ``System.out.print(board[i][j]);``                ``if` `(j < ``2``) {``                    ``System.out.print(" | ");``                ``}``            ``}``            ``System.out.println();``            ``if` `(i < ``2``) {``                ``System.out.println("---------");``            ``}``        ``}``    ``}` `    ``public` `boolean` `isBoardFull()``    ``{``        ``for` `(``int` `i = ``0``; i < ``3``; ++i) {``            ``for` `(``int` `j = ``0``; j < ``3``; ++j) {``                ``if` `(board[i][j] == ``' '``) {``                    ``return` `false``;``                ``}``            ``}``        ``}``        ``return` `true``;``    ``}` `    ``public` `boolean` `makeMove(``int` `row, ``int` `column)``    ``{``        ``if` `(row < ``0` `|| row >= ``3` `|| column < ``0` `|| column >= ``3``            ``|| board[row][column] != ``' '``) {``            ``return` `false``; ``// Invalid move``        ``}``        ``board[row][column]``            ``= (currentPlayer == ``1``) ? ``'X'` `: ``'O'``;``        ``currentPlayer``            ``= ``3` `- currentPlayer; ``// Switch player (1 to 2 or``                                 ``// 2 to 1)``        ``return` `true``;``    ``}` `    ``public` `boolean` `checkWinner()``    ``{``        ``// Check rows, columns, and diagonals for a win``        ``for` `(``int` `i = ``0``; i < ``3``; ++i) {``            ``if` `(board[i][``0``] != ``' '``                ``&& board[i][``0``] == board[i][``1``]``                ``&& board[i][``1``] == board[i][``2``]) {``                ``return` `true``; ``// Row win``            ``}``            ``if` `(board[``0``][i] != ``' '``                ``&& board[``0``][i] == board[``1``][i]``                ``&& board[``1``][i] == board[``2``][i]) {``                ``return` `true``; ``// Column win``            ``}``        ``}``        ``if` `(board[``0``][``0``] != ``' '` `&& board[``0``][``0``] == board[``1``][``1``]``            ``&& board[``1``][``1``] == board[``2``][``2``]) {``            ``return` `true``; ``// Diagonal win``        ``}``        ``if` `(board[``0``][``2``] != ``' '` `&& board[``0``][``2``] == board[``1``][``1``]``            ``&& board[``1``][``1``] == board[``2``][``0``]) {``            ``return` `true``; ``// Diagonal win``        ``}``        ``return` `false``;``    ``}` `    ``public` `static` `void` `main(String[] args)``    ``{``        ``TicTacToe game = ``new` `TicTacToe();``        ``Scanner scanner = ``new` `Scanner(System.in);``        ``int` `row, column;` `        ``while` `(!game.isBoardFull() && !game.checkWinner()) {``            ``game.printBoard();` `            ``System.out.print(``                ``"Player " + game.currentPlayer``                ``+ ", enter your move (row and column): ");``            ``row = scanner.nextInt();``            ``column = scanner.nextInt();` `            ``if` `(game.makeMove(row, column)) {``                ``System.out.println("Move successful!");``            ``}``            ``else` `{``                ``System.out.println(``                    ``"Invalid move. Try again.");``            ``}``        ``}` `        ``game.printBoard();` `        ``if` `(game.checkWinner()) {``            ``System.out.println("Player "``                               ``+ (``3` `- game.currentPlayer)``                               ``+ " wins!");``        ``}``        ``else` `{``            ``System.out.println("It's a draw!");``        ``}` `        ``scanner.close();``    ``}``}`

Python3

 `class` `TicTacToe:``    ``def` `__init__(``self``):``        ``self``.board ``=` `[[``' '` `for` `_ ``in` `range``(``3``)] ``for` `_ ``in` `range``(``3``)]``        ``self``.current_player ``=` `1` `    ``def` `print_board(``self``):``        ``for` `row ``in` `self``.board:``            ``print``(``'|'``.join(row))``            ``print``(``'-'` `*` `5``)` `    ``def` `is_board_full(``self``):``        ``return` `all``(cell !``=` `' '` `for` `row ``in` `self``.board ``for` `cell ``in` `row)` `    ``def` `make_move(``self``, row, column):``        ``if` `0` `<``=` `row < ``3` `and` `0` `<``=` `column < ``3` `and` `self``.board[row][column] ``=``=` `' '``:``            ``self``.board[row][column] ``=` `'X'` `if` `self``.current_player ``=``=` `1` `else` `'O'``            ``# Switch player (1 to 2 or 2 to 1)``            ``self``.current_player ``=` `3` `-` `self``.current_player``            ``return` `True``        ``return` `False` `    ``def` `check_winner(``self``):``        ``for` `i ``in` `range``(``3``):``            ``if` `self``.board[i][``0``] ``=``=` `self``.board[i][``1``] ``=``=` `self``.board[i][``2``] !``=` `' '``:``                ``return` `True`  `# Row win``            ``if` `self``.board[``0``][i] ``=``=` `self``.board[``1``][i] ``=``=` `self``.board[``2``][i] !``=` `' '``:``                ``return` `True`  `# Column win``        ``if` `self``.board[``0``][``0``] ``=``=` `self``.board[``1``][``1``] ``=``=` `self``.board[``2``][``2``] !``=` `' '``:``            ``return` `True`  `# Diagonal win``        ``if` `self``.board[``0``][``2``] ``=``=` `self``.board[``1``][``1``] ``=``=` `self``.board[``2``][``0``] !``=` `' '``:``            ``return` `True`  `# Diagonal win``        ``return` `False`  `# Main game loop``if` `__name__ ``=``=` `"__main__":``    ``game ``=` `TicTacToe()` `    ``while` `not` `game.is_board_full() ``and` `not` `game.check_winner():``        ``game.print_board()` `        ``row, column ``=` `map``(``int``, ``input``(``            ``f"Player {game.current_player}, enter your move (row ``and` `column): ").split())` `        ``if` `game.make_move(row, column):``            ``print``("Move successful!")``        ``else``:``            ``print``("Invalid move. Try again.")` `    ``game.print_board()` `    ``if` `game.check_winner():``        ``print``(f"Player {``3` `-` `game.current_player} wins!")``    ``else``:``        ``print``("It's a draw!")`

Javascript

 `class TicTacToe {``    ``constructor() {``        ``this``.board = Array.from(Array(3), () => Array(3).fill(``' '``)); ``// 3x3 game board``        ``this``.currentPlayer = 1; ``// 1 for Player 1, 2 for Player 2``    ``}` `    ``printBoard() {``        ``for` `(let i = 0; i < 3; ++i) {``            ``for` `(let j = 0; j < 3; ++j) {``                ``process.stdout.write(``this``.board[i][j]);``                ``if` `(j < 2) {``                    ``process.stdout.write(``' | '``);``                ``}``            ``}``            ``console.log();``            ``if` `(i < 2) {``                ``console.log(``'---------'``);``            ``}``        ``}``    ``}` `    ``isBoardFull() {``        ``for` `(let i = 0; i < 3; ++i) {``            ``for` `(let j = 0; j < 3; ++j) {``                ``if` `(``this``.board[i][j] === ``' '``) {``                    ``return` `false``;``                ``}``            ``}``        ``}``        ``return` `true``;``    ``}` `    ``makeMove(row, column) {``        ``if` `(``            ``row < 0 ||``            ``row >= 3 ||``            ``column < 0 ||``            ``column >= 3 ||``            ``this``.board[row][column] !== ``' '``        ``) {``            ``return` `false``; ``// Invalid move``        ``}``        ``this``.board[row][column] = ``this``.currentPlayer === 1 ? ``'X'` `: ``'O'``;``        ``this``.currentPlayer = 3 - ``this``.currentPlayer; ``// Switch player (1 to 2 or 2 to 1)``        ``return` `true``;``    ``}` `    ``checkWinner() {``        ``// Check rows, columns, and diagonals for a win``        ``for` `(let i = 0; i < 3; ++i) {``            ``if` `(``                ``this``.board[i][0] !== ``' '` `&&``                ``this``.board[i][0] === ``this``.board[i][1] &&``                ``this``.board[i][1] === ``this``.board[i][2]``            ``) {``                ``return` `true``; ``// Row win``            ``}``            ``if` `(``                ``this``.board[0][i] !== ``' '` `&&``                ``this``.board[0][i] === ``this``.board[1][i] &&``                ``this``.board[1][i] === ``this``.board[2][i]``            ``) {``                ``return` `true``; ``// Column win``            ``}``        ``}``        ``if` `(``            ``this``.board[0][0] !== ``' '` `&&``            ``this``.board[0][0] === ``this``.board[1][1] &&``            ``this``.board[1][1] === ``this``.board[2][2]``        ``) {``            ``return` `true``; ``// Diagonal win``        ``}``        ``if` `(``            ``this``.board[0][2] !== ``' '` `&&``            ``this``.board[0][2] === ``this``.board[1][1] &&``            ``this``.board[1][1] === ``this``.board[2][0]``        ``) {``            ``return` `true``; ``// Diagonal win``        ``}``        ``return` `false``;``    ``}``}` `function` `main() {``    ``const game = ``new` `TicTacToe();``    ``const readline = require(``'readline-sync'``);``    ``let row, column;` `    ``while` `(!game.isBoardFull() && !game.checkWinner()) {``        ``game.printBoard();` `        ``console.log(`Player \${game.currentPlayer}, enter your move (row and column): `);``        ``row = parseInt(readline.question(``'Row: '``));``        ``column = parseInt(readline.question(``'Column: '``));` `        ``if` `(game.makeMove(row, column)) {``            ``console.log(``'Move successful!'``);``        ``} ``else` `{``            ``console.log(``'Invalid move. Try again.'``);``        ``}``    ``}` `    ``game.printBoard();` `    ``if` `(game.checkWinner()) {``        ``console.log(`Player \${3 - game.currentPlayer} wins!`);``    ``} ``else` `{``        ``console.log(``"It's a draw!"``);``    ``}``}` `main();``// This code is contributed by Vikram_Shirsat`

Conclusion

The game of Tic Tac Toe, often deemed simplistic, hides layers of intriguing design choices beneath its surface. From crafting the game board to managing turns and deciphering wins, every aspect intertwines to deliver an immersive gaming experience. As we delve into the low-level design using C++, we uncover the harmony between code and gameplay, reminding us that even seemingly uncomplicated games hold within them a realm of thoughtful intricacies.

So the next time you engage in a round of Tic Tac Toe, take a moment to appreciate the elegance of its designâ€”a design that transforms an ordinary grid into a battlefield of strategic brilliance.