Click here to Skip to main content
Click here to Skip to main content
Go to top

TicTacToe in C#

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

Sample Image

Introduction

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

Background

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.

History

No updates so far.

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

Share

About the Author

TheGrandInquisitor

United States United States
No Biography provided

Comments and Discussions

 
General[Message Deleted] PinmemberDanny Rodriguez27-Jan-08 9:19 
Generalminimize crash PinmemberThe_Grand_Inquisitor6-Mar-06 6:55 
GeneralRe: minimize crash PinmemberIkado12-Aug-08 21:38 
GeneralRe: minimize crash PinmemberChris Congdon13-Feb-10 6:54 
GeneralRe: minimize crash PinmemberChris Congdon13-Feb-10 7:02 
GeneralSome Suggestions On C# Coding PinprotectorMarc Clifton6-Mar-06 6:21 
GeneralRe: Some Suggestions On C# Coding PinmemberThe_Grand_Inquisitor6-Mar-06 6:43 
GeneralRe: Some Suggestions On C# Coding PinmemberRay Cassick6-Mar-06 7:13 
GeneralRe: Some Suggestions On C# Coding PinmemberChris Congdon13-Feb-10 6:22 
GeneralRe: Some Suggestions On C# Coding [modified] PinmemberChris 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 | Mobile
Web04 | 2.8.140916.1 | Last Updated 6 Mar 2006
Article Copyright 2006 by TheGrandInquisitor
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid