Click here to Skip to main content
15,861,172 members
Articles / Desktop Programming / Windows Forms
Article

Tic Tac Toe in C#

Rate me:
Please Sign up or sign in to vote.
4.66/5 (28 votes)
5 Jun 20024 min read 289.3K   10.4K   47   12
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:

C#
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:

C#
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:

C#
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.

C#
_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...

C#
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:

C#
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.

C#
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.

C#
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


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionvery useful as basic practical wpf demo. Pin
edthehorse12-Mar-24 4:26
edthehorse12-Mar-24 4:26 
Questionprogramar en capas en c# Pin
Member 1305956714-Mar-17 19:42
Member 1305956714-Mar-17 19:42 
AnswerRe: programar en capas en c# Pin
Thanks787214-Mar-17 19:42
professionalThanks787214-Mar-17 19:42 
QuestionThank you very much Pin
Member 1103192924-Aug-14 6:06
Member 1103192924-Aug-14 6:06 
QuestionGood one put an updated version soon Pin
kathirvel mariappan26-Mar-14 23:53
kathirvel mariappan26-Mar-14 23:53 
QuestionInformation Pin
Rami abdul Jabbar2-Apr-13 8:49
Rami abdul Jabbar2-Apr-13 8:49 
GeneralMy vote of 5 Pin
mahaSidhartha18-Feb-12 12:35
mahaSidhartha18-Feb-12 12:35 
Questionquestion Pin
ivan_go29-Jun-11 22:33
ivan_go29-Jun-11 22:33 
GeneralMy vote of 1 Pin
wassem_k6-Jan-10 5:00
wassem_k6-Jan-10 5:00 
Generalnice game to beginners Pin
dpi17-Jan-03 2:09
dpi17-Jan-03 2:09 
GeneralA suggestion... Pin
James T. Johnson6-Jun-02 18:34
James T. Johnson6-Jun-02 18:34 

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

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