Click here to Skip to main content
11,790,613 members (52,121 online)
Click here to Skip to main content

TicTacToe in C#

, 6 Mar 2006 70.9K 2.8K 21
Rate this:
Please Sign up or sign in to vote.
A C# implementation of Tic-Tac-Toe using Minimax look-ahead.

Sample Image


This is an implementation of the game Tic-Tac-Toe, written in C#.


I wrote this program as a basic exercise to improve my coding skills. It is admittedly quite simple, but since I am a novice programmer, it was adequately challenging. This article is intended for other novices who are interested in board games and/or Windows Forms, but looking for a simple example to get them started.

If you are not a novice, but you'd like to look at my code and provide constructive criticism, please do! I am not receiving any formal instruction, so any feedback you provide will be greatly appreciated.

Using the code

Simply compile the source files and run the resulting executable. Try resizing the window.

Points of Interest

Program Structure

The program is divided into three classes: Board, SquareControl, and TicTacToe.

The Board class

The game board is represented by a two-dimensional integer array. The public field BoardState denotes whether the game is in progress, and if not, what the previous outcome was. The possible values for BoardState are defined by the GameState enumeration. The public field iEmptySquares keeps count of the empty squares on the board to facilitate the detection of a draw.

The Board class provides two public constructors. One creates a new, empty board, while the other creates a new board by copying an existing one. The second constructor is used during the game by the AI.

The CheckBoard() method is used to check the board for a winner after every call to MakeMove().

The SquareControl class

This class inherits from UserControl, and is used to represent each square in the UI. The OnPaint() method is overridden.

Initially, I had a flickering problem with SquareControl objects. To resolve this, I set up double-buffering in the OnPaint() method. The most commonly prescribed method for double-buffering in Windows Forms involves several calls to the SetStyles() method to set up automatic double-buffering. However, this didn't work for me, so I did it this way:

//Use a back-buffer to reduce flicker
Graphics buffer = Graphics.FromImage(bmpBackBuffer);
buffer.SmoothingMode = SmoothingMode.AntiAlias;

//....draw onto buffer as needed

//draw the contents of buffer to the screen
Graphics viewable = pea.Graphics;
viewable.DrawImageUnscaled(bmpBackBuffer, 0, 0);

The TicTacToe class

This class represents the main (and only) form of the program. TicTacToe contains several methods for controlling the game play. For example, the MakeMove() method is responsible for applying a given move to the Board object and the appropriate SquareControl. The Reset() method is used to reset the Board and SquareControl objects in preparation for a new game. TicTacToe also contains the AI code.

Game AI

The GetBestMove() method employs the Minimax look-ahead algorithm to determine the best possible move for the computer player. Alpha-beta pruning is used to increase performance. A Google search will turn up plenty of information on this topic.

The look-ahead is executed in a worker thread in order to avoid hanging the UI during the search. When the search is completed, the worker thread makes a callback to the main thread to apply the new move. Check the CalculateComputerMove() and MakeComputerMove() methods to see how this is done.

Because the search space for a 3x3 Tic-Tac-Toe game is relatively small, I decided not to limit the depth of the search. This simplified the scoring system used during the look-ahead. In order to adapt the algorithm to boards any larger, a depth limit and a new evaluation function would need to be implemented. You may notice that the computer player occasionally chooses to forgo an immediate win, but only to fork you so that you lose on the computer's next move anyway. I thought about adding a preference to win as soon as possible, but I decided that this behavior was cute.


No updates so far.


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

United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

General[Message Deleted] Pin
Danny Rodriguez27-Jan-08 9:19
memberDanny Rodriguez27-Jan-08 9:19 
Generalminimize crash Pin
The_Grand_Inquisitor6-Mar-06 6:55
memberThe_Grand_Inquisitor6-Mar-06 6:55 
GeneralRe: minimize crash Pin
Ikado12-Aug-08 21:38
memberIkado12-Aug-08 21:38 
GeneralRe: minimize crash Pin
Chris Congdon13-Feb-10 6:54
memberChris Congdon13-Feb-10 6:54 
GeneralRe: minimize crash Pin
Chris Congdon13-Feb-10 7:02
memberChris Congdon13-Feb-10 7:02 
GeneralSome Suggestions On C# Coding Pin
Marc Clifton6-Mar-06 6:21
protectorMarc Clifton6-Mar-06 6:21 
GeneralRe: Some Suggestions On C# Coding Pin
The_Grand_Inquisitor6-Mar-06 6:43
memberThe_Grand_Inquisitor6-Mar-06 6:43 
Thank you for taking the time to give me some good suggestions. Clearly I need improvement, and it's also important that nobody is led astray by any poor practices I have.

I know the use of "this" is unnecessary, but I thought it could help readability for those with poor memories (it reminds you that you're referring to an instance field of the current class). That said, I don't think I was very consistent in this practice. Would anyone else care to comment on this?

As for the MiniMaxTest class that is commented out, I simply forgot to remove that code file before submitting the project. Sorry! That was used exclusively for debugging the look-ahead method.

I'll try to add the improvements you recommended and update the article as soon as possible. I know you're right about using a UserControl for each square, but I'm not sure what the solution is. Perhaps one UserControl for the entire board?

GeneralRe: Some Suggestions On C# Coding Pin
Ray Cassick6-Mar-06 7:13
memberRay Cassick6-Mar-06 7:13 
GeneralRe: Some Suggestions On C# Coding Pin
Chris Congdon13-Feb-10 6:22
memberChris Congdon13-Feb-10 6:22 
GeneralRe: Some Suggestions On C# Coding [modified] Pin
Chris Congdon13-Feb-10 7:16
memberChris Congdon13-Feb-10 7:16 

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 | Terms of Use | Mobile
Web01 | 2.8.1509028.1 | Last Updated 6 Mar 2006
Article Copyright 2006 by TheGrandInquisitor
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid