CreateJs tic-tac-toe game source code

index.js

import * as createjs from "createjs-module";
function startGame() {
  console.log("satya");
  const stage = new createjs.Stage("gameCanvas");

  const board = [
    ["", "", ""],
    ["", "", ""],
    ["", "", ""]
  ];
  let currentPlayer = "X";

  function drawBoard() {
    stage.removeAllChildren();

    for (let row = 0; row < 3; row++) {
      for (let col = 0; col < 3; col++) {
        const cell = new createjs.Shape();
        cell.graphics
          .beginFill("#f0f0f0")
          .drawRect(col * 100, row * 100, 100, 100)
          .beginStroke("#000") // Add border stroke color
          .drawRect(col * 100, row * 100, 100, 100); // Draw border
        cell.addEventListener("click", () => handleCellClick(row, col));
        stage.addChild(cell);

        const text = new createjs.Text(board[row][col], "24px Arial", "#000");
        text.x = col * 100 + 40;
        text.y = row * 100 + 30;
        stage.addChild(text);
      }
    }

    stage.update();
  }

  // below is for two user player
  // function handleCellClick(row, col) {
  //   if (board[row][col] === "" && currentPlayer !== "") {
  //     board[row][col] = currentPlayer;
  //     drawBoard();
  //     checkWinCondition();
  //     currentPlayer = currentPlayer === "X" ? "O" : "X";
  //   }
  // }

  // below for AI enable
  // not needed for two user player start
  function handleCellClick(row, col) {
    if (board[row][col] === "" && currentPlayer === "X") {
      board[row][col] = currentPlayer;
      drawBoard();
      checkWinCondition();
      currentPlayer = "O";

      // Let the system make a move after a delay
      setTimeout(makeSystemMove, 500);
    }
  }

  function makeSystemMove() {
    const bestMove = findBestMove(board);
    if (bestMove !== -1) {
      const row = Math.floor(bestMove / 3);
      const col = bestMove % 3;

      board[row][col] = currentPlayer;
      drawBoard();
      checkWinCondition();
      currentPlayer = "X";
    }
  }

  function findBestMove(currentBoard) {
    let bestMove = -1;
    let bestScore = -Infinity;

    for (let i = 0; i < 9; i++) {
      if (currentBoard[Math.floor(i / 3)][i % 3] === "") {
        const newBoard = copyBoard(currentBoard);
        newBoard[Math.floor(i / 3)][i % 3] = "O";

        const score = minimax(newBoard, 0, false);

        if (score > bestScore) {
          bestScore = score;
          bestMove = i;
        }
      }
    }

    return bestMove;
  }

  function copyBoard(board) {
    const copy = [];
    for (let i = 0; i < board.length; i++) {
      copy.push([...board[i]]);
    }
    return copy;
  }

  const checkWinner = (currentBoard) => {
    const winningPatterns = [
      [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 (const pattern of winningPatterns) {
      const [a, b, c] = pattern;
      if (
        currentBoard[a] &&
        currentBoard[a] === currentBoard[b] &&
        currentBoard[a] === currentBoard[c]
      ) {
        return currentBoard[a];
      }
    }

    if (currentBoard.every((cell) => cell !== null)) {
      return "draw";
    }

    return null;
  };

  const minimax = (currentBoard, depth, isMaximizing) => {
    const winner = checkWinner(currentBoard);

    if (winner === "O") {
      return 1;
    } else if (winner === "X") {
      return -1;
    } else if (winner === "draw") {
      return 0;
    }

    if (isMaximizing) {
      let bestScore = -Infinity;

      for (let i = 0; i < 9; i++) {
        if (currentBoard[i] === null) {
          const newBoard = currentBoard.slice();
          newBoard[i] = "O";
          const score = minimax(newBoard, depth + 1, false);
          bestScore = Math.max(bestScore, score);
        }
      }

      return bestScore;
    } else {
      let bestScore = Infinity;

      for (let i = 0; i < 9; i++) {
        if (currentBoard[i] === null) {
          const newBoard = currentBoard.slice();
          newBoard[i] = "X";
          const score = minimax(newBoard, depth + 1, true);
          bestScore = Math.min(bestScore, score);
        }
      }

      return bestScore;
    }
  };
  // not needed for two user player end

  function checkWinCondition() {
    const winningPatterns = [
      [
        [0, 0],
        [0, 1],
        [0, 2]
      ],
      [
        [1, 0],
        [1, 1],
        [1, 2]
      ],
      [
        [2, 0],
        [2, 1],
        [2, 2]
      ],
      [
        [0, 0],
        [1, 0],
        [2, 0]
      ],
      [
        [0, 1],
        [1, 1],
        [2, 1]
      ],
      [
        [0, 2],
        [1, 2],
        [2, 2]
      ],
      [
        [0, 0],
        [1, 1],
        [2, 2]
      ],
      [
        [0, 2],
        [1, 1],
        [2, 0]
      ]
    ];

    for (const pattern of winningPatterns) {
      const [a, b, c] = pattern;
      if (
        board[a[0]][a[1]] !== "" &&
        board[a[0]][a[1]] === board[b[0]][b[1]] &&
        board[a[0]][a[1]] === board[c[0]][c[1]]
      ) {
        alert(`Player ${board[a[0]][a[1]]} wins!`);
        resetGame();
        return;
      }
    }

    if (board.flat().every((cell) => cell !== "")) {
      alert("It's a draw!");
      resetGame();
    }
  }

  function resetGame() {
    for (let row = 0; row < 3; row++) {
      for (let col = 0; col < 3; col++) {
        board[row][col] = "";
      }
    }
    drawBoard();
  }

  drawBoard();
}

setTimeout(function () {
  startGame();
}, 3000);
styles.css

body {
  font-family: sans-serif;
  display: block;
  text-align: center;
  width: 100%;
}

canvas {
  display: block;
  margin: 0 auto;
  width: 300px;
}
index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Tic-Tac-Toe with EaselJS</title>
    <!-- <script src="https://code.createjs.com/1.0.0/createjs.min.js"></script> -->
  </head>
  <body>
    <canvas id="gameCanvas" width="300" height="300"></canvas>
    <script src="game.js"></script>
  </body>
</html>

Codesandbox example here

In this code, the findBestMove function iterates through the empty cells on the game board and simulates placing the AI player’s (‘O’) piece in each of them. It then calculates the score using the minimax algorithm to evaluate the potential outcome of that move. The copyBoard function is used to create a copy of the game board to avoid modifying the original board during simulations.

Remember that the minimax algorithm involves a depth-first search of the game tree, which can become slow for larger games. You can consider optimizations like alpha-beta pruning to improve performance if needed.

With this findBestMove function, your AI opponent should be able to make informed decisions and provide a challenging game experience for the player.

Leave a Reply

Your email address will not be published. Required fields are marked *.

*
*
You may use these <abbr title="HyperText Markup Language">HTML</abbr> tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>