TypeScript Tutorial

TypeScript Project: Tic-Tac-Toe

A 3x3 board as a string array. 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 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 so the winner is the same every run. That keeps the demo deterministic at/typescript/try. Use Try it in TypeScript.

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

function emptyBoard(): string[] {
  return [" ", " ", " ", " ", " ", " ", " ", " ", " "];
}

function printBoard(b: string[]): void {
  console.log(" " + b[0] + " | " + b[1] + " | " + b[2]);
  console.log("---+---+---");
  console.log(" " + b[3] + " | " + b[4] + " | " + b[5]);
  console.log("---+---+---");
  console.log(" " + b[6] + " | " + b[7] + " | " + b[8]);
}

const board: string[] = emptyBoard();
printBoard(board);

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

function place(b: string[], cell: number, mark: string): boolean {
  if (cell < 0 || cell > 8) {
    return false;
  }
  if (b[cell] !== " ") {
    return false;
  }
  b[cell] = mark;
  return true;
}

const board: string[] = [" ", " ", " ", " ", " ", " ", " ", " ", " "];
console.log(place(board, 0, "X"));
console.log(place(board, 0, "O"));
console.log(place(board, 9, "X"));
console.log("cell 0 is " + board[0]);

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

Run this at /typescript/try with Try it in TypeScript. The printedtrue and false values 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

function winner(b: string[]): string {
  const lines: number[][] = [
    [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 (let i = 0; i < 8; i++) {
    const a = b[lines[i][0]];
    const c = b[lines[i][1]];
    const d = b[lines[i][2]];
    if (a !== " " && a === c && c === d) {
      return a;
    }
  }
  return " ";
}

const board: string[] = [" ", " ", " ", " ", " ", " ", " ", " ", " "];
board[0] = "X";
board[1] = "X";
board[2] = "X";
console.log("Winner: [" + winner(board) + "]");

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

function printBoard(b: string[]): void {
  console.log(" " + b[0] + " | " + b[1] + " | " + b[2]);
  console.log("---+---+---");
  console.log(" " + b[3] + " | " + b[4] + " | " + b[5]);
  console.log("---+---+---");
  console.log(" " + b[6] + " | " + b[7] + " | " + b[8]);
}

function place(b: string[], cell: number, mark: string): boolean {
  if (cell < 0 || cell > 8 || b[cell] !== " ") {
    return false;
  }
  b[cell] = mark;
  return true;
}

function winner(b: string[]): string {
  const lines: number[][] = [
    [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 (let i = 0; i < 8; i++) {
    const a = b[lines[i][0]];
    const c = b[lines[i][1]];
    const d = b[lines[i][2]];
    if (a !== " " && a === c && c === d) {
      return a;
    }
  }
  return " ";
}

const board: string[] = [" ", " ", " ", " ", " ", " ", " ", " ", " "];
const moves: number[] = [0, 3, 1, 4, 2];
const marks: string[] = ["X", "O", "X", "O", "X"];

for (let i = 0; i < 5; i++) {
  console.log(marks[i] + " plays cell " + moves[i]);
  if (!place(board, moves[i], marks[i])) {
    console.log("Illegal move");
    break;
  }
  printBoard(board);
  const w = winner(board);
  if (w !== " ") {
    console.log(w + " wins");
    break;
  }
  console.log("");
}

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

Common mistakes

  • Using a 3 by 3 nested array 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. Change the last X move from cell 2 to cell 8 and confirm the program no longer prints a winner.
  2. Add a sixth move for O at cell 5 and confirm the middle row then wins for O if X did not already win.
  3. After nine legal moves with no winner, print Draw, and write a function that returns how many empty cells remain.

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

FAQ: TypeScript Project: Tic-Tac-Toe

Common questions about this page.

What is the StudyGrid TypeScript tutorial?

The StudyGrid TypeScript tutorial follows the same chapter rhythm as C++: syntax, types, input, loops, functions, classes, generics, maps, and lambdas. Each chapter has copy-and-run examples.

Should I run typescript 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 typescript tictactoe project in this TypeScript TypeScript lesson (TypeScript Project: Tic-Tac-Toe).

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

No. Try TypeScript type-checks with tsc at /typescript/try and shows stdout plus compiler messages. Try Python stays at /try. Try C++ stays at /cpp/try. TypeScript lessons never open those editors.

Do I need to install a compiler to learn TypeScript?

No. Open a chapter, click Try it in TypeScript, and compile in the browser. You can also download a .ts file and compile locally with tsc.

Where should I start the TypeScript tutorial?

Start at TypeScript Intro, then Get Started and Syntax. After the first program, continue to output, variables, and if-else. After classes, open TypeScript Examples, then generics, Map, and arrow functions. Use Next at the bottom of each chapter.

Is the TypeScript tutorial free?

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