C++ Tutorial

C++ Project: Tic-Tac-Toe

A 3x3 board as a vector of strings. Place marks, print the grid, and detect a winner.

What you will build

Tic-tac-toe is a 3 by 3 grid. This project stores nine cells in a vector<string>. Empty cells are a single space. Players place X and O. After each move you print the board and check rows, columns, and diagonals for a winner.

Moves are a fixed sequence in main so the winner is the same every run. That keeps the demo deterministic at /cpp/try. Use Try it in C++.

Nine cells

Index 0 is top-left. Index 2 is top-right. Index 8 is bottom-right. Printing uses three cells per line with bars between them. A helper builds an empty board so tests start from the same state.

Example

#include <iostream>
#include <string>
#include <vector>
using namespace std;

vector<string> emptyBoard() {
  return vector<string>(9, " ");
}

void printBoard(const vector<string>& b) {
  cout << " " << b[0] << " | " << b[1] << " | " << b[2] << endl;
  cout << "---+---+---" << endl;
  cout << " " << b[3] << " | " << b[4] << " | " << b[5] << endl;
  cout << "---+---+---" << endl;
  cout << " " << b[6] << " | " << b[7] << " | " << b[8] << endl;
}

int main() {
  vector<string> board = emptyBoard();
  printBoard(board);
  return 0;
}

Place a mark

A legal move needs an index from 0 through 8 and an empty cell. Return false when the cell is taken or the index is out of range. Do not overwrite an existing mark.

Example

#include <iostream>
#include <string>
#include <vector>
using namespace std;

bool place(vector<string>& b, int cell, const string& mark) {
  if (cell < 0 || cell > 8) {
    return false;
  }
  if (b[cell] != " ") {
    return false;
  }
  b[cell] = mark;
  return true;
}

int main() {
  vector<string> board(9, " ");
  cout << place(board, 0, "X") << endl;
  cout << place(board, 0, "O") << endl;
  cout << place(board, 9, "X") << endl;
  cout << "cell 0 is " << board[0] << endl;
  return 0;
}

First place succeeds and prints 1. Second place on the same cell fails and prints 0. Index 9 is invalid. Cell 0 still holds X.

Run this at /cpp/try with Try it in C++. The printed 1 and 0 arebool values. They are enough to see which calls were accepted.

Detect a winner

Eight lines can win: three rows, three columns, two diagonals. If all three cells in a line share a mark that is not a space, that mark wins. Return that string, or a space when there is no winner yet.

Example

#include <iostream>
#include <string>
#include <vector>
using namespace std;

string winner(const vector<string>& b) {
  const int lines[8][3] = {
      {0, 1, 2}, {3, 4, 5}, {6, 7, 8},
      {0, 3, 6}, {1, 4, 7}, {2, 5, 8},
      {0, 4, 8}, {2, 4, 6}};
  for (int i = 0; i < 8; i++) {
    string a = b[lines[i][0]];
    string c = b[lines[i][1]];
    string d = b[lines[i][2]];
    if (a != " " && a == c && c == d) {
      return a;
    }
  }
  return " ";
}

int main() {
  vector<string> board(9, " ");
  board[0] = "X";
  board[1] = "X";
  board[2] = "X";
  cout << "Winner: [" << winner(board) << "]" << endl;
  return 0;
}

The top row is three X marks, so the function returns X.

Complete game, fixed moves

X starts. The sequence fills the top row for X while O takes the middle row’s first two cells. After each successful place, print the board and stop if someone has won. There is no keyboard input, so the transcript never changes.

Example

#include <iostream>
#include <string>
#include <vector>
using namespace std;

void printBoard(const vector<string>& b) {
  cout << " " << b[0] << " | " << b[1] << " | " << b[2] << endl;
  cout << "---+---+---" << endl;
  cout << " " << b[3] << " | " << b[4] << " | " << b[5] << endl;
  cout << "---+---+---" << endl;
  cout << " " << b[6] << " | " << b[7] << " | " << b[8] << endl;
}

bool place(vector<string>& b, int cell, const string& mark) {
  if (cell < 0 || cell > 8 || b[cell] != " ") {
    return false;
  }
  b[cell] = mark;
  return true;
}

string winner(const vector<string>& b) {
  const int lines[8][3] = {
      {0, 1, 2}, {3, 4, 5}, {6, 7, 8},
      {0, 3, 6}, {1, 4, 7}, {2, 5, 8},
      {0, 4, 8}, {2, 4, 6}};
  for (int i = 0; i < 8; i++) {
    string a = b[lines[i][0]];
    string c = b[lines[i][1]];
    string d = b[lines[i][2]];
    if (a != " " && a == c && c == d) {
      return a;
    }
  }
  return " ";
}

int main() {
  vector<string> board(9, " ");
  int moves[5] = {0, 3, 1, 4, 2};
  string marks[5] = {"X", "O", "X", "O", "X"};

  for (int i = 0; i < 5; i++) {
    cout << marks[i] << " plays cell " << moves[i] << endl;
    if (!place(board, moves[i], marks[i])) {
      cout << "Illegal move" << endl;
      return 0;
    }
    printBoard(board);
    string w = winner(board);
    if (w != " ") {
      cout << w << " wins" << endl;
      return 0;
    }
    cout << endl;
  }
  cout << "No winner yet" << endl;
  return 0;
}

X takes cells 0, 1, and 2. After the fifth move the top row is full and the program printsX wins. Change the last X move to cell 8 and you should see No winner yet instead.

Common mistakes

  • Using a 3 by 3 nested vector and then mixing up row and column. Nine cells and a printed grid keep the index rule in one place: row * 3 + col if you add coordinates later.
  • Checking only rows. Columns and diagonals are how most first games are actually won.
  • Treating three spaces as a win. The empty mark must be excluded or a blank board wins on the first row.
  • Allowing a second mark in a filled cell. Always test b[cell] != " " before you assign.

Practice

  1. After nine legal moves with no winner, print Draw.
  2. Add a sequence where O wins on a diagonal (cells 2, 4, 6) and confirm the message.
  3. Write a function that returns how many empty cells remain, and print it after each move.

Next project: a contact book keyed by name in a map.

FAQ: C++ Project: Tic-Tac-Toe

Common questions about this page.

What is the StudyGrid C++ tutorial?

The StudyGrid C++ tutorial is a full beginner-to-advanced track: syntax, types, input, loops, functions, classes, the STL, templates, maps, and lambdas. Each chapter has copy-and-run examples.

Should I run c++ tictactoe project examples locally for better learning?

Yes. Use the browser editor on StudyGrid for a quick check, then Download the example and run it on your computer. Local runs show real errors and the real toolchain, which is one of the fastest ways to learn c++ tictactoe project in this C++ C++ lesson (C++ Project: Tic-Tac-Toe).

Is the C++ editor the same as Try Python or Try HTML?

No. Try C++ compiles with g++ at /cpp/try and shows stdout plus compiler messages. Try Python stays at /try. Try HTML stays at /html/try. C++ lessons never open those editors.

Do I need to install a compiler to learn C++?

No. Open a chapter, click Try it in C++, and compile in the browser. You can also download a .cpp file and compile locally with g++.

Where should I start the C++ tutorial?

Start at C++ Intro, then Get Started and Syntax. After the first program, continue to output, variables, and if-else. After classes, open C++ Examples, then templates, map, and lambdas. Use Next at the bottom of each chapter.

Is the C++ tutorial free?

Yes. The C++ workshop on StudyGrid (studygrid.in) is free: dashboard, chapters, and the compile-and-run editor.