Tic Tac Toe in C#






4.66/5 (24 votes)
Jun 6, 2002
4 min read

291209

10414
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 Button
s 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 Button
s but does not create any Button
s. 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:
- Check to see if the game is over.
- Make sure the
Button
’s text is empty – otherwise it's already been played. - Place the X or O in the square.
- 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 Button
s 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 Button
s with drawing (GDI+) calls, saving the game’s state, printing, converting this to a web page and separating the logic into a Web Service.