Home Store Project Ideas Project Guide Ask An Expert Blog Careers Teachers Parents Students

Artificial Intelligence: Teaching the Computer to Play Tic-Tac-Toe

Difficulty
Time Required Average (6-10 days)
Prerequisites To do this project, you should already be comfortable with creating basic HTML files using a text editor. You should also be familiar with creating HTML form elements, and having them interact with JavaScript functions.
Material Availability Readily available
Cost Very Low (under $20)
Safety No issues

Abstract

This is a more challenging JavaScript project: can you write a program that can play Tic-Tac-Toe? You'll have to figure out a way to translate the game strategy into a computer algorithm. The project will show you how to create a working Tic-Tac-Toe board on a webpage. Your challenge will be to show the computer how to play. Just think: you'll be creating artificial intelligence!

Objective

The goal of this project is to write a JavaScript program that plays Tic-Tac-Toe. This project will take you through the steps of creating the interface for the game. You will need to take it from there and write the algorithms to create a computer opponent.

Credits

By Adam Schepis, Software Engineer

Edited by Andrew Olson, Ph.D., Science Buddies

Cite This Page

MLA Style

Science Buddies Staff. "Artificial Intelligence: Teaching the Computer to Play Tic-Tac-Toe" Science Buddies. Science Buddies, 21 Apr. 2014. Web. 23 Sep. 2014 <http://www.sciencebuddies.org/science-fair-projects/project_ideas/Games_p014.shtml>

APA Style

Science Buddies Staff. (2014, April 21). Artificial Intelligence: Teaching the Computer to Play Tic-Tac-Toe. Retrieved September 23, 2014 from http://www.sciencebuddies.org/science-fair-projects/project_ideas/Games_p014.shtml

Share your story with Science Buddies!

I did this project I Did This Project! Please log in and let us know how things went.


Last edit date: 2014-04-21

Introduction

This is an example of an intermediate programming project. You will be writing a program that allows you to play a game of Tic-Tac-Toe against the computer.

To do this project, you should already be comfortable with creating basic HTML files using a text editor. You should also be familiar with creating HTML form elements, and having them interact with JavaScript functions. If you have not done any JavaScript programming before, we suggest you start with a simpler project, like Forms and Functions: Writing a Simple Calculator Program with JavaScript or ABC's of Programming: Writing a Simple 'Alphabetizer' with JavaScript.

The Introduction will help you get started, in a step-by-step manner. If you follow the steps in the Introduction, you can gradually build up a webpage that you can use to play Tic-Tac-Toe with a friend. The experience you gain from building the two-player game will help you when you take on the challenge of programming the computer to play against you.

Here are the steps covered in the Introduction. First you will learn how to write an HTML file (webpage) that represents a Tic-Tac-Toe board. Next you will learn how to make your webpage respond to mouse clicks on the Tic-Tac-Toe board using JavaScript. Then you will learn how to update the text values of HTML elements on the fly. You will also learn how to program Tic-Tac-Toe knowledge into your program to detect when the game has been won or ended in a draw. At this point, you'll have a webpage that you can use to play Tic-Tac-Toe with a friend.

The challenge we leave you with for your project is to write the algorithms so that the computer can be your opponent instead. Can you create a computer opponent that always gives you opportunities to win? Can you improve that opponent so that it plays strongly but sometimes gives you an opportunity to win? Finally, we all know that it is possible to play a perfect game of Tic-Tac-Toe that results in a draw. Can you write an AI player that never loses?

The important HTML elements used in this project are:

SCRIPT The <SCRIPT> element is used to begin and end a section of JavaScript code.
INPUT The <INPUT> element can be used to create buttons. Buttons will represent the squares of our Tic-Tac-Toe board in this lesson.
P The <P> element is used to create paragraphs. We will use this element to create a space that tells the user what is going on in the game.
This element stands for "non-breaking space." It is used in HTML to place a space on the webpage where no line-break can occur. We will use non-breaking spaces to represent empty squares on the Tic-Tac-Toe board.

The important JavaScript objects, functions, and keywords used in this project are:

Var The var keyword is used to declare a variable in JavaScript. A variable is a piece of data in JavaScript that can be changed and compared to other variables.
function The function keyword is used to declare the beginning of a function. A function is a reusable piece of code that performs a specific purpose. In this project you will use functions to do things such as: place an X or an O on the game board, or check to see if someone has won the game, or to start a new game after one has finished.
== , != The operators "is equal to" (==) and "is not equal to" (!=) are used to compare values in JavaScript. There are also comparison operators for "less than" (<), "less than or equal to" (<=), "greater than" (>), and "greater than or equal to" (>=). The result of using a comparison operator is either true or false. Comparison operators are used in if statements and for loops to control program execution (see next two entries).
if...else An if statement is a conditional statement. It is used to control the flow of the program using simple true/false expressions. For example, you might have a variable to indicate whose turn it is (X or O). When there is a mouse click on a blank square, you can use an if statement to check the value of the turn variable so you know whether to mark the square with an X or an O.
for The for keyword is used to loop through a section of code a number of times. In this project we will use loops to check each value on the game board.


Making a JavaScript Tic-Tac-Toe Board
  1. Laying out the game board. In this project, the game board is made up of buttons. There are 3 rows that each have 3 button across. Each button represents a square on the Tic-Tac-Toe board. The HTML code necessary to lay this out is easy. To do this, we use the HTML <INPUT> tag. The input tag must have a type. In our case the type is "BUTTON".

    <INPUT TYPE="BUTTON" ID="0_0" VALUE="   ">
    <INPUT TYPE="BUTTON" ID="1_0" VALUE="   ">
    <INPUT TYPE="BUTTON" ID="2_0" VALUE="   ">
    <BR>
    <INPUT TYPE="BUTTON" ID="0_1" VALUE="   ">
    <INPUT TYPE="BUTTON" ID="1_1" VALUE="   ">
    <INPUT TYPE="BUTTON" ID="2_1" VALUE="   ">
    <BR>
    <INPUT TYPE="BUTTON" ID="0_2" VALUE="   ">
    <INPUT TYPE="BUTTON" ID="1_2" VALUE="   ">
    <INPUT TYPE="BUTTON" ID="2_2" VALUE="   ">
    <BR>
    Notice that each input has an "ID" and a "VALUE." The VALUE is displayed on the face of the button. At the start of the game, the buttons are blank. The ID can be used to tell which button was pressed. We will also use the ID to change individual buttons to show an X or an O.

  2. "Catching" mouse clicks. In order to make the Tic-Tac-Toe game interactive you will need to know when the user clicks on a button. JavaScript provides an easy way to do this. <INPUT> tags can have an ONCLICK attribute that you can use to call JavaScript code whenever the button is clicked. This must be added to each button on our board like so:

    <INPUT TYPE="BUTTON" ID="0_0" VALUE=" " ONCLICK="alert('Hi, you clicked me!');">

    Now you will know whenever a player clicks on a button. The next step is putting the right value into the box. After that, we'll tackle alternative turns!

  3. Setting the value of a square. The first step in making the Tic-Tac-Toe game work is setting the value of a square when it is clicked. Each of the squares will work in the same way. Because the click response is common to all of the squares, you should write one piece of code that can be used by any square when it is clicked. To do this you need to create a JavaScript function. At the top of your HTML file (in the <HEAD> section) add a <SCRIPT> tag so you can write JavaScript code, like this:

    <SCRIPT TYPE="TEXT/JAVASCRIPT">
    </SCRIPT>

    Now you can write JavaScript code inside the script section. Let's start by creating the function we will call whenever a button is clicked:

    function squareclicked(square)
    // squareclicked is a function that is called whenever a button is clicked.
    {
    }

    These four lines create a function that will do nothing. The first line is a comment. It summarizes what the function does. The function is named "squareclicked," and it has one argument, "square." The argument will be used to tell the function which button has been clicked. This means you need to update your buttons to call the squareclicked() function:

    <INPUT TYPE="BUTTON" ID="0_0" VALUE=" " ONCLICK="squareclicked(this);">

    Notice how "this" is being sent whenever we call the squareclicked() function. When you put "this" inside an onclick attribute it represents the <INPUT> that the onclick attribute is created in. This means that whenever a button is clicked it will call the squareclicked() function and pass itself to the function. This will enable you to set the value of the square. Now update the squareclicked() function to set the value of the button:

    function squareclicked(square)
    // squareclicked is a function that is called whenever a button is clicked.
    {
       square.value = 'X';
    }

    Jackpot! Now whenever a button is clicked it gets the value 'X'. The next step is to put the right value in the square based on whose turn it is.

  4. Alternating turns. In order to alternate turns and place the right value in the square that is clicked we will need to keep track of whose turn it is. You can do this by creating a "global" variable (a global variable can be accessed from any function) in the JavaScript section outside of the squareclicked() function, like this:

    <SCRIPT TYPE="TEXT/JAVASCRIPT">
    var xTurn = true;

    function squareclicked(square)
    // squareclicked is a function that is called whenever a button is clicked.
    {
     ... code here ...
    }
    </SCRIPT>

  5. Using the xTurn variable. The next step is to use the xTurn variable in the squareclicked() function to put the right marker (X or O) onto the board, depending on whose turn it is. After marking the square, the function should switch whose turn it is.

    function squareclicked(square)
    // squareclicked is a function that is called whenever a button is clicked.
    {
     var value = square.value;
     if(value != 'X' && value != 'O')
     {
       if(xTurn)
       {
          square.value = 'X';
          xTurn = false;
       }
       else
          {
             square.value = 'O';
             xTurn = true;
          }
     }
       else
          alert('That square has already been played.');
    }

    This function will mark squares and switch turns appropriately. Notice how the outer if ... else statements prevent a square from being chosen more than once. The inner if ... else statements check the xTurn variable, mark the square with the correct market, and switch the xTurn variable to the next player.

    It would be really nice if we could tell the players whose turn it is, though. Let's add a status bar.

  6. Adding a status bar. To add a status bar we will need to add a section near the bottom of our HTML page (above the </body> tag):

    <P ID="status">X's turn</P>

    The "ID" attribute is very important because it will allow us to change the value of the status bar later! Update the squareclicked function to use the status bar:

    function squareclicked(square)
    // squareclicked is a function that is called whenever a button is clicked.
    {
     var status = document.getElementById('status');
     var value = square.value;
     if(value != 'X' && value != 'O')
     {
       if(xTurn)
       {
          square.value = 'X';
          xTurn = false;
          status.innerHTML = 'O\'s turn';
       }
       else
          {
             square.value = 'O';
             xTurn = true;
             status.innerHTML = 'X\'s turn';
          }
     }
       else
          alert('That square has already been played.');
    }

  7. Starting a new game. The last thing we need to do in order to have a functioning Tic-Tac-Toe board is give the players a way to start a new game. You can add a button to do this:

    <INPUT TYPE="BUTTON" ID="NEWGAME" VALUE="New Game" ONCLICK="newgame();">

    This button calls the function "newgame()," which we haven't written yet. The newgame() function must reset everything that is necessary to start the game anew:

    function newgame()
    {
       var status = document.getElementById('status');

       xTurn = true;
       status.innerHTML = 'X\'s turn';

       for(var x = 0; x < x++)    {
          for(var y = 0; y < y++)       {
             document.getElementById(x + '_' + y).value = ' ';
          }
       }
    }

Checking for the End of the Game

You have now successfully made a program that lets two players play a game of Tic-Tac-Toe. You can make this game better by detecting when the game has ended (win, lose or draw). To do this we need to do several things.

  1. First we need to create a global variable to keep track of whether or not the game is over:

    var gameOver = false;

  2. Next we need to keep track of how many moves have been made. If 9 moves have been made and nobody has won then we know all of the spaces on the board have been filled, and we have a tie. We'll create a global variable to keep track of the number of moves that have been made:

    var numMoves = 0;

  3. Now you can write a function that checks to see if a player has won. Call it checkWin(). The checkWin function will determine if a player has won by checking every row, every column, and both diagonals to see if any of them are made up entirely of X's or O's. The function will return a value of either "true" or "false" indicating whether or not someone has won:

    function checkWin()
    {
     var status = document.getElementById('status');
     var val0;
     var val1;
     var val2;

     // check columns
     for(var y = 0; y < y++)  {
       val0 = document.getElementById('0_'+y).value;
       val1 = document.getElementById('1_'+y).value;
       val2 = document.getElementById('2_'+y).value;
       if(val0 == 'X' && val1 == 'X' && val2 == 'X')
       {
          status.innerHTML = "X WINS!";
          return true;
       }
       else if(val0 == 'O' && val1 == 'O' && val2 == 'O')
       {
          status.innerHTML = "O WINS!";
          return true;
       }
     }

     // check rows
     for(var x = 0; x < x++)  {
       val0 = document.getElementById(x + '_0').value;
       val1 = document.getElementById(x + '_1').value;
       val2 = document.getElementById(x + '_2').value;
       if(val0 == 'X' && val1 == 'X' && val2 == 'X')
       {
          status.innerHTML = "X WINS!";
          return true;
       }
       else if(val0 == 'O' && val1 == 'O' && val2 == 'O')
       {
          status.innerHTML = "O WINS!";
          return true;
       }
     }

     // check top left to lower right diagonal
     val0 = document.getElementById('0_0').value;
     val1 = document.getElementById('1_1').value;
     val2 = document.getElementById('2_2').value;
     if(val0 == 'X' && val1 == 'X' && val2 == 'X')
     {
       status.innerHTML = "X WINS!";
       return true;
     }
     else if(val0 == 'O' && val1 == 'O' && val2 == 'O')
     {
       status.innerHTML = "O WINS!";
       return true;
     }

     // check lower left to top right diagonal
     val0 = document.getElementById('2_0').value;
     val1 = document.getElementById('1_1').value;
     val2 = document.getElementById('0_2').value;
     if(val0 == 'X' && val1 == 'X' && val2 == 'X')
     {
       status.innerHTML = "X WINS!";
     return true;
     }
     else if(val0 == 'O' && val1 == 'O' && val2 == 'O')
     {
       status.innerHTML = "O WINS!";
       return true;
     }

     // no winner yet  return false;
    }

  4. We also need to incorporate the gameOver variable, the numMoves variable, and the checkWin() function into the newGame() function and the squareclicked()function. The newGame() function needs to set gameOver = false, and numMoves = 0:

    numMoves = 0;
    gameOver = false;

  5. The squareclicked() function will need three updates.
    1. You will need to check at the beginning of the squareClicked function to see if the game is over (so the players can't make moves after the game is over):

       if(gameOver)
       {
         alert("The game is already over.");
         return;
       }

    2. You will need to increment numMoves each time a player takes a turn:

         if(xTurn)
         {
            numMoves++;
            square.value = 'X';
            xTurn = false;
            status.innerHTML = 'O\'s turn';
         }
         else
         {
            numMoves++;
            square.value = 'O';
            xTurn = true;
            status.innerHTML = 'X\'s turn';
         }

    3. You will need to check at the bottom of the squareClicked function (after a move has been made) to see if there is a winner or a tie:

       var winner = checkWin();
       if(!winner)
       {
         //check to see if there is a tie
         if(numMoves == 9)
            status.innerHTML = 'Tie Game!';
       }
       else
         gameOver = true;

Creating a Computer Opponent

Now that you have created a working game of Tic-Tac-Toe for two players wouldn't it be nice to have someone to play against? How about playing against the computer? This requires artificial intelligence to the game. What is involved in adding artificial intelligence? Check out the Experimental Procedure section!

Terms and Concepts

To do this project, you should do research that enables you to understand the following terms and concepts:

  • HTML concepts:
    • start tags and end tags,
    • comments,
    • the <HEAD> section,
    • the <SCRIPT> section,
    • the <BODY> section,
    • the <FORM> section,
    • the <INPUT> tag,
  • JavaScript concepts:
    • functions,
    • variables,
    • objects,
    • events,
  • general programming concepts:
    • reserved words,
    • control statements (e.g., if...else statements, for loops),
    • recursion,
    • artificial intelligence.

Questions:

  • How do you program a button in an HTML form to call a JavaScript function?
  • How do you pass information from an HTML form to a JavaScript function using a variable?
  • How do you program a JavaScript function to display information in an HTML form?

Bibliography

  • HTML Forms reference:
    W3C. (1999). Forms in HTML Documents, HTML 4.01 Specification. World Wide Web Consortium: Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University. Retrieved June 6, 2006, from http://www.w3.org/TR/REC-html40/interact/forms.html
  • A list of reserved words in JavaScript (you cannot use these words for function or variable names in your program, because they are reserved for the programming language itself):
    JavaScript Kit. (2006). JavaScript Reserved Words. Retrieved June 6, 2006, from http://www.JavaScriptkit.com/jsref/reserved.shtml
  • A JavaScript reference:
    Mozilla Developer Network and Individual Contributors. (2013, December 14). JavaScript reference. Retrieved March 14, 2014, from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference
  • You can find a step-by-step JavaScript tutorial at the link below. If you need help with the JavaScript concepts covered in this project, this tutorial should help:
    Webteacher Software. (2006). JavaScript Tutorial for the Total Non-Programmer. Webteacher Software, LLC. Retrieved June 6, 2006, from http://www.webteacher.com/javascript/index.html
  • Introduction to Programming by Matt Gemmell describes what programming actually is:
    Gemmell, M. (2007). Introduction to Programming. Dean’s Director Tutorials & Resources. Retrieved March 14, 2014, from http://www.deansdirectortutorials.com/Lingo/IntroductionToProgramming.pdf
  • If you get interested and start doing a lot of web development, you may want to use a text editor that is a little more sophisticated than Notepad. An editor designed for web development and programming can help with formatting so that your code is more readable, but still produce plain text files. This type of editor can also fill in web-specific HTML coding details and do "syntax highlighting" (e.g., automatic color-coding of HTML), which can help you find errors. One option is the CoffeeCup HTML Editor, which is available in the following formats:

Materials and Equipment

To do this experiment you will need the following materials and equipment:

Experimental Procedure

The Introduction took you through the steps to create a working Tic-Tac-Toe game that you could play with a friend. The next step is to program the computer to play the game in place of one player. You'll be adding a simple form of artificial intelligence (AI) to your program! What is involved in adding AI to the program? Several things:

  1. The computer must know when it is has the turn to move.
    1. Your program can keep track of this with another global variable:

      var computerTurn = false; // true/false variable to keep track of the turn

    2. Whenever a move is made, you can switch the value of the computerTurn variable, like this:

      computerTurn = !computerTurn

  2. There must be code in place to make a move! You can use a code snippet like the one below, but where should you put it? You should be able to figure this out on your own!

     if(computerTurn)
     {
       makeComputerMove();
     }

  3. How will the computer determine where to place its X or O? In other words, what will go into the "makeComputerMove()" function? You'll have to think about Tic-Tac-Toe strategy, and try to reduce it to a series of steps that you can write in a program. For example, the computer could mark the first empty spot it finds, or it could choose a random empty spot, or it could look for places where the opponent has 2 in a row in order to block, or it could look for places where it has 2 in a row so it could win. It could also be a mix of all of the above! This is entirely up to you but it's easy to see that some methods will produce a better computer opponent than others.
  4. Whatever strategy you choose you will most likely have to loop through all the squares. The code in the checkWin() function should help you figure out what to do.
  5. It's a good idea to follow the method used in the Introduction. Start out with something simple, get it working, and then refine it. As you improve your program, remember save your previous version, and re-name the file before making radical changes. That way, you can always go back to a working version.
  6. Can you create a computer opponent that always gives you opportunities to win? Can you improve that opponent so that it plays strongly but sometimes gives you an opportunity to win?
  7. When you have a working computer opponent, make a prediction about how well the computer's strategy will work. Test your prediction by playing a few dozen games against the computer, and record the results of each game. How did your prediction hold up? How can you improve the computer's performance? Refine the program and try again!
  8. Hint: to make the computer place an O, use document.getElementById(‘ID’).value = "O"; where you replace ID with the button's ID (look at the code where you created the buttons for their IDs).

Share your story with Science Buddies!

I did this project I Did This Project! Please log in and let us know how things went.


Variations

  • Once you've created one computer opponent, why not try having the computer play against itself? Have the program run in a loop, with input from the HTML form to set the number of games. The program should also keep track of the results. You can give the two players different strategies. Predict which strategy will be stronger, and test your prediction by having the computer play a few hundred games against itself. Try this for several different strategies.
  • We all know that it is possible to play a perfect game of Tic-Tac-Toe, so that the result is always a draw. Can you write an AI player that never loses?
  • Advanced. The most complex and powerful AI game opponents will use a technique called recursion. Recursion is when you write a function that calls itself again in certain cases. This would be used by the AI player to evaluate the outcome of moves that it could make in the future. By doing this the AI player can "look ahead" to make a better decision about what moves to play.

Share your story with Science Buddies!

I did this project I Did This Project! Please log in and let us know how things went.

Ask an Expert

The Ask an Expert Forum is intended to be a place where students can go to find answers to science questions that they have been unable to find using other resources. If you have specific questions about your science fair project or science fair, our team of volunteer scientists can help. Our Experts won't do the work for you, but they will make suggestions, offer guidance, and help you troubleshoot.

Ask an Expert

Related Links

If you like this project, you might enjoy exploring these related careers:

Computer programmer typing on a keyboard

Computer Programmer

Computers are essential tools in the modern world, handling everything from traffic control, car welding, movie animation, shipping, aircraft design, and social networking to book publishing, business management, music mixing, health care, agriculture, and online shopping. Computer programmers are the people who write the instructions that tell computers what to do. Read more
NASA flight software engineer

Computer Software Engineer

Are you interested in developing cool video game software for computers? Would you like to learn how to make software run faster and more reliably on different kinds of computers and operating systems? Do you like to apply your computer science skills to solve problems? If so, then you might be interested in the career of a computer software engineer. Read more
Software quality engineer working on database

Software Quality Assurance Engineer & Tester

Software quality assurance engineers and testers oversee the quality of a piece of software's development over its entire life cycle. Their goal is to see to it that the final product meets the customer's requirements and expectations in both performance and value. During the software life cycle, they verify (officially state) that it is possible for the software to accomplish certain tasks. They detect problems that exist in the process of developing the software, or in the product itself. They try and make things not work (try to "break" the software) by creating errors or combinations of errors that a user might make. For example, if a user enters a period or a pound sign for a password, will that break the software? They seek to anticipate potential issues with the software before they become visible. At the end of the life cycle, they reflect upon how problems or bugs arose, and figure out ways to make the software development process better in the future. Read more

Looking for more science fun?

Try one of our science activities for quick, anytime science explorations. The perfect thing to liven up a rainy day, school vacation, or moment of boredom.

Find an Activity