A terminal-based Tic Tac Toe game written in C++, played on a numeric grid (positions 1–9) against a bot with random move logic. This was my third C++ project and my biggest leap in complexity yet — I rewrote my previous Tic Tac Toe from scratch using a proper 2D array, cleaner function design, and a much better approach to planning before coding.
==========================================================
TIC TAC TOE IMPROVED
==========================================================
_____ ___ ____ _____ _ ____ _____ ___ _____
|_ _|_ _|/ ___| |_ _|/ \ / ___| |_ _|/ _ \| ____|
| | | || | | | / _ \| | | | | | | | _|
| | | || |___ | |/ ___ \ |___ | | | |_| | |___
|_| |___|\___| |_/_/ \_\____| |_| \___/|_____|
I M P R O V E D
==========================================================
1 | 2 | 3
___|___|___
4 | 5 | 6
___|___|___
7 | 8 | 9
| |
Please choose a position to play
Choice: 5
X | 2 | 3
___|___|___
4 | O | 6
___|___|___
7 | 8 | 9
| |
Bot move:
- Numeric grid input — positions 1–9 mapped to a visual board shown before every move
- 2D array board — the entire board lives in a single
char[3][3]array - Occupied cell validation — can't place on a cell that's already taken
- Input validation — handles letters and out-of-range numbers without crashing
- Win detection — checks all rows, columns, and both diagonals after every move for both X and O
- Tie detection — correctly identifies a draw when all 9 cells are filled
- Random bot — the bot picks valid moves at random using
rand() - ASCII art banner — clean title screen on launch
The board is stored as a single char[3][3] 2D array initialized with spaces. Player input (1–9) is mapped to row and column indices using simple integer arithmetic:
int row = (move - 1) / 3;
int col = (move - 1) % 3;This means position 1 maps to [0][0], position 5 to [1][1], and position 9 to [2][2]. A reference board with numbers is shown before every turn so the player always knows which number maps to which cell.
Win detection checks all 8 possible winning combinations (3 rows, 3 columns, 2 diagonals) for both X and O after every move.
- Language: C++
- Compiler: g++ / GCC
- Libraries:
<iostream>,<ctime>
- g++ compiler installed (MinGW on Windows, or built-in on Linux/macOS)
# 1. Clone the repository
git clone https://github.com/YOUR_USERNAME/Cpp-TicTacToe-Improved.git
# 2. Navigate into the folder
cd Cpp-TicTacToe-Improved
# 3. Compile the source file
g++ main.cpp -o tictactoe
# 4. Run the game
./tictactoe # Linux / macOS
tictactoe.exe # WindowsThis was my third C++ project and a massive step forward compared to my previous Tic Tac Toe. Here's what I took away:
- Multidimensional arrays — for the first time I used a proper
char[3][3]2D array to represent the board instead of three separate 1D arrays; managing rows and columns together in one structure felt much more natural and made the logic significantly cleaner - Index arithmetic — mapping a single number (1–9) to a 2D position using
(move-1)/3and(move-1)%3was a great exercise in thinking about how flat and grid-based representations relate to each other - Passing 2D arrays to functions — learned how C++ handles multidimensional arrays when passed to functions and how to correctly declare them in function signatures
- Boolean references — continued using
bool &someoneWonas a reference parameter to pass state between functions without a return value, and got more comfortable with why references are useful - Planning before coding — coming off the previous project where I got lost mid-way, this time I thought through the data structure and function responsibilities first; the whole project went much smoother because of it
- Separating concerns — kept display logic (
printBoard,notationPrintBoard), game logic (checkWin,checkMoveValidity), and input logic (getPlayerChoice) clearly separated into their own functions
Switching to a 2D array was the core challenge of this project. In my previous Tic Tac Toe I used three separate char arrays for the rows, which worked but felt messy — every function needed three separate parameters just to represent the board. Moving to a single char[3][3] required understanding how 2D arrays work in memory and how to pass them correctly to functions. Getting the indexing right and making sure every function was reading and writing the correct cell took real thought.
The position-to-index mapping was also trickier than it looked. Figuring out the formula to convert a number from 1–9 into a [row][col] pair — and then verifying it worked correctly for all 9 positions — was satisfying to solve cleanly.
The biggest improvement over my last project though was planning. Last time I got lost in the middle because I started coding without a clear picture of the structure. This time I mapped out what data I needed, how it would be stored, and what each function was responsible for before writing a single line. The difference was enormous.
- Add a proper AI using the Minimax algorithm (unbeatable bot)
- Add difficulty levels (random bot vs smart bot)
- Add a "who goes first?" option like in v1
- Add a play again option without restarting
- Rewrite using classes and OOP (v2)
This project is open source under the MIT License.
Third project. Better structure, better habits, better code. Still learning. 🚀