Click here to Skip to main content
Click here to Skip to main content

Tic Tac Toe in C#

, 5 Jun 2002
Rate this:
Please Sign up or sign in to vote.
An article using a simple game to explore more complex constructions.

Introduction

Etudes are technical studies for musicians who concentrate on a fully complete musical idea but in a small form. Often, there are a variety of these smaller pieces that solve the same problem and differ in the details. This concept can be borrowed for learning computer languages.

In this article, a functioning Tic-Tac-Toe program is developed - it might not be the fullest implementation, but it works. The program concentrates on a sensible implementation that might serve as a foundation for possibly more intricate implementations. The following assumes you are familiar with the rules of Tic-Tac-Toe – if not, take a minute to look them up. Also, a basic understanding of C#, WinForms, VS.NET and data structures is assumed.

Tic-Tac-Toe is a simple game but has a number of interesting issues like:

  • How to represent each square and how should it be addressed?
  • How to process the mouse click on the box and trap errors/incorrect mouse clicks?
  • What is the best way to determine if someone has won?

The first design choice is made to represent the game squares with the Button control. With this control, there is a simple way to change the text from blank to an X or Y, establish an event handler for the Click event and easily address them as a group. By using this control, we can concentrate on other design decisions without struggling with many technical details.

Starting with the default Windows project, add nine (3x3) buttons with the same dimensions arranged 3x3. Each of the Buttons is called but1, but2, etc. Another Button, labeled Play, is added to trigger a new game. Finally, the form is titled Tic Tac Toe for Windows32.

Without any code, the project should look like:

To check for winners, the buttons need to be addressed as a group. You could use the Controls array, but then extra processing would be required to account for the non-box buttons – like the Play button. Also discarded was placing them in an ArrayList construct – as this has too much overhead. Finally, we settle on the single dimensional array.

To place them in an array, a variable is created that holds the objects. The declaration is:

private System.Windows.Forms.Button [] _buttonArray;

It is really critical to understand that this statement allocates space to hold Buttons but does not create any Buttons. If you try to immediately access the _buttonArray members without creating and assigning a new Button, an exception will be thrown. For example, the code fragment:

private System.Windows.Forms.Button [] _buttonArray = new Button[9];

_buttonArray[0].Text = “It will throw an exception!”;

will throw an error since there is no object there -- only undefined space. The proper way would be:

private System.Windows.Forms.Button [] _buttonArray = new Button[9];

_buttonArray[0] = new Button();    //  <-- Allocate the object!
_buttonArray[0].Text = “Save”;    // No problem now...

Back to the program...Once the buttons are created in InitializeComponent(), they can be placed in the array using automatic initialization.

_buttonArray = new Button[9] {but1, but2, but3, but4, but5, but6, but7, but8, but9};

The next task is to establish the event handler for the Click event. In this routine, we need to:

  1. Check to see if the game is over.
  2. Make sure the Button’s text is empty – otherwise it's already been played.
  3. Place the X or O in the square.
  4. Check to see if either X or O has won.

The code below implements this function...

private void ClickHandler(object sender, System.EventArgs e)
{
    Button tempButton = (Button)sender;
            
    if( this._isGameOver )
    {
        MessageBox.Show("Game Over...Select Play for a new game!",
                        "ERROR",MessageBoxButtons.OK);
        return;            
    }

    if( tempButton.Text != "" )    // if not empty..already has X or O
    {
        MessageBox.Show("Button already has value!","ERROR",MessageBoxButtons.OK);
        return;
    }

    if( _isX )    // Alternate putting the X or O character in the Text property
        tempButton.Text = "X";  
    else
        tempButton.Text = "O";

    _isX = !_isX;    // alternate characters

    // check to see if there is a winner
    this._isGameOver = TicTacToeUtils.CheckAndProcessWinner(_buttonArray );
    }

The code to attach the Click event handler to the array of Buttons is:

for(int i = 0; i < 9; i++)
    this._buttonArray[i].Click += new System.EventHandler(this.ClickHandler);

The strategy to determine who won is to cycle through all the winning combinations. The winning combinations are stored in a three dimensional array. Each time a square is selected, the program checks to see if there is a winner.

static private int [,] Winners = new int[,]
   {
    {0,1,2},
    {3,4,5},
    {6,7,8},
    {0,3,6},
    {1,4,7},
    {2,5,8},
    {0,4,8},
    {2,4,6}
   };

All that is required now is to loop through this array to check for winners. As well, it is a really good design to have a visual (and sometimes auditory) signal when something significant happens. In this instance, the color and font is changed for the winning three buttons.

static public bool CheckAndProcessWinner( Button [] myControls )
{
    bool gameOver = false;
    for(int i = 0; i < 8; i++)
    {
        int a = Winners[i,0],b=Winners[i,1],c=Winners[i,2];
        Button b1=myControls[a], b2=myControls[b], b3=myControls[c];

        if(b1.Text == "" || b2.Text == "" || b3.Text == "" ) // if one if blank
            continue;    // try another -- no need to go further

        if(b1.Text == b2.Text && b2.Text == b3.Text )
        {
            b1.BackColor = b2.BackColor = b3.BackColor = Color.LightCoral;
            b1.Font = b2.Font = b3.Font
                 = new System.Drawing.Font("Microsoft Sans Serif", 32F, 
                                           System.Drawing.FontStyle.Italic & 
                                           System.Drawing.FontStyle.Bold, 
                                           System.Drawing.GraphicsUnit.Point, 
                                           ((System.Byte)(0)));
            gameOver = true;
            break;  // don't bother to continue
        }
    }    
    return gameOver;
}

A completed game might look like:

Pressing the Play returns the game back to the default setting and readies it for another game.

At this point, it makes sense to run review and run the code. Please let me know what you think – I’ll be working on the next Tic-Tac-Toe Etude. There are more interesting design decisions that would make a different implementation– like making a Tic-Tac-Toe Windows control, replacing the Buttons with drawing (GDI+) calls, saving the game’s state, printing, converting this to a web page and separating the logic into a Web Service.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Grant Richard
Web Developer
United States United States
No Biography provided

Comments and Discussions

 
QuestionGood one put an updated version soon Pinmemberkathirvel mariappan26-Mar-14 23:53 
QuestionInformation PinmemberRami abdul Jabbar2-Apr-13 8:49 
GeneralMy vote of 5 PinmembermahaSidhartha18-Feb-12 12:35 
Questionquestion Pinmemberivan_go29-Jun-11 22:33 
GeneralMy vote of 1 Pinmemberwassem_k6-Jan-10 5:00 
Generalnice game to beginners Pinmemberdpi17-Jan-03 2:09 
GeneralA suggestion... PinsubeditorJames T. Johnson6-Jun-02 18:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 6 Jun 2002
Article Copyright 2002 by Grant Richard
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid