DEV Community

Marcos
Marcos

Posted on

Tic-Tac-Toe JavaScript game for beginners

Tic-tac-toe is a classic game played on a grid of 3x3 squares. Two players take turns marking X or O in empty squares, aiming to get three of their marks in a row, either horizontally, vertically, or diagonally. It's a quick and strategic game often enjoyed by people of all ages.

Is a seemingly straightforward game that offers valuable problem-solving opportunities, particularly for beginners. This article provides a step-by-step explanation of how to create the game using an HTML Canvas element and JavaScript.

The tools

  • JavaScript: It is versatile, compatible with browsers, and supports both front-end and back-end development.

  • HTML: It organizes and presents information on the web.

  • CSS: It separates content and design, facilitating maintenance and updates.

If you want to delve deeper into the subject, I'll leave my recommended readings below:

  1. "Eloquent JavaScript" by Marijn Haverbeke
  2. "HTML and CSS: Design and Build Websites" by Jon Duckett
  3. "CSS Secrets: Better Solutions to Everyday Web Design Problems" by Lea Verou

The Concepts

  • Class: It's like a template for party invitations, defining the design and basic information. In JavaScript, a class is a blueprint for creating objects with properties and methods.

  • Object: It's like a personalized party invitation representing a distinct object with unique details. In JavaScript, an object is an instance of a class, representing a specific entity with its own characteristics and actions.

  • Constructor: It's how you prepare invitations, defining the basic structure and initial information. In JavaScript, the constructor is a special method within a class that initializes the object's properties for use.

Inicial Setup

To start, create an HTML file with the basic structure, including a canvas element and a script tag. While you can separate the JavaScript code into a different file, for this tutorial, we'll keep everything in one file.

The canvas element acts as the background for the game's scene. If desired, you can adapt the game to work with other elements like a div tag, but that would require modifying the code provided in this tutorial.

Figure 1
Figure 1: This part demonstrates a basic HTML structure that includes a canvas element and a script tag.

The Game’s Classes

Classes in JavaScript provide a way to organize code by creating objects with related properties and methods. In the Tic-Tac-Toe game, we have the TicTacToe class for managing the game instance and the Square class for representing each square on the game board.

The TicTacToe class takes the ID of a canvas element as a parameter, which is used for rendering graphics. The Square class stores position and click information, and has methods for drawing and displaying symbols on the canvas.

Now, let's see how these concepts are applied in the game code.

Figure 2
Figure 2: This is how our basic structure for the game will look like.

When creating a instance, the canvas element ID is passed as a parameter, allowing multiple instances for different screen elements. The Square class represents a square on the game board, storing position, size, and click information. It provides methods to draw the square and display the player's symbol.

The Square class generates square objects for a 3x3 grid. It has properties such as x, y, width, height, ctx, and actor. x and y determine the position, width and height define the dimensions, ctx references the canvas interface, and actor indicates the player's symbol ('x' or 'o').

In JavaScript, a constructor is a special function that creates and initializes objects. It establishes the object's properties and methods. To call a constructor, we use the new keyword followed by the constructor function's name. The constructor function associates the new object with the this variable, allowing us to define the object's properties.

When instantiating a Square object, all properties except actor should be provided to the constructor. The actor property should be set to null within the constructor to ensure it exists on Square objects.

Figure 3
Figure 3: Demonstrates the implementation of the Square class.

The class should include a draw() method responsible for rendering a square and displaying the symbol of the player who interacted with it. The draw() method utilizes the strokeRect(x, y, width, height) method, accessed through the ctx property, to draw the square on the canvas. Additionally, the ctx property provides access to the strokeStyle property, allowing for customization of the border color.

Figure 4
Figure 4: Demonstrates the implementation of the draw() method.

The draw method utilizes the fillText(text, x, y) method from the ctx property to inscribe the symbol of the player who interacted with the square. The text is precisely placed at the square's center by adding half of its width and height to its x and y positions. The ctx property also possesses a textAlign property that can be set to center, ensuring the text is perfectly aligned towards the center.

Next, we proceed with creating the TicTacToe class, which entails a constructor and three essential methods: click(event), checkForWinner(), and reset().

Figure 5
Figure 5: Demonstrates the implementation of a TicTacToe class.

The TicTacToe class constructor requires a canvas element id as input. The id is used to fetch the corresponding HTML canvas element using getElementById(id) and assigned to the canvas property. The canvas property is then used to obtain a CanvasRenderingContext2D instance assigned to the ctx property, serving as the drawing interface within the canvas.

Figure 6
Figure 6: Demonstrates the implementation of a TicTacToe class constructor.

To instantiate the Square objects, a loop of 3x3 is performed, creating a Square object for each iteration and adding it to the squares property. The loop starts at (x=0, y=0) and continues until 9 squares are created.

The class requires three additional properties: actors (an array of two strings representing the players and their symbols 'x' and 'o'), turn (a number between 0-1 specifying the next player's turn), and gameOver (a boolean indicating if the game has ended).

In the constructor, the square objects draw() method is called, and a click event listener is added to the class click() method.

The click method is triggered when the user clicks on the canvas, and it retrieves the cursor's position from the event argument. The first section of the click method includes a guard clause that resets the game if the gameOver property is set to true, allowing the user to start a new game by clicking on the canvas.

Figure 7
Figure 7: Demonstrates the implementation of a TicTacToe class click method.

The method iterates over Square objects, checking if the mouse position is within a square. If true, the actor is added to the square's actor property to indicate selection. The turn property allows the next player to choose.

The method then calls checkForWinner() to determine if there is a winner. It checks for three squares selected in a horizontal, vertical, or diagonal line.

Using an array of arrays, the method checks if three squares match any winning combinations. If true, gameOver is set to true, resetting the game on the next canvas click.

The method also draws a line and displays the winner's text representing the winning combination.

Figure 8
Figure 8: Displays the implementation of the checkForWinner() method in the TicTacToe class.

The final part of the method checks if all squares have a non-null actor, indicating that the game is a draw. This check is performed after determining if there is a winner to ensure that the game is not mistakenly considered a draw when the last empty square is selected and a winner is found.

The reset method is responsible for restoring the properties of a TicTacToe instance to their initial values, preparing for a new game.

Firstly, the method clears the canvas by using the clearRect(x, y, width, height) method of the ctx property.

After clearing the canvas, the actor property of each square is set to null, and the squares are redrawn on the canvas.

Finally, the method resets the turn to 0, allowing players to take turns again, and sets gameOver to false. This indicates that the click() method can assign players to squares and search for a new winner or a draw.

Figure 9
Figure 9: Illustrates how the reset() method is implemented within the TicTacToe class.

The game is now fully prepared and ready for players to engage. To begin, simply add a new line below the class definitions to instantiate a fresh instance of the class. This will initialize all the necessary game components and set the stage for an exciting gameplay experience.

So go ahead, create a new instance and let the gaming fun begin!

Figure 10
Figure 10: Demonstrates the process of initiating the Tic-tac-toe game.


You can find this code through the following link: https://github.com/marcconci/educational-tic-tac-toe. Additionally, you can also access my GitHub page through it.

Top comments (0)