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
The program is divided into three classes:
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.
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.
CheckBoard() method is used to check the board for a winner after every call to
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:
Graphics buffer = Graphics.FromImage(bmpBackBuffer);
buffer.SmoothingMode = SmoothingMode.AntiAlias;
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
Reset() method is used to reset the
SquareControl objects in preparation for a new game.
TicTacToe also contains the AI code.
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
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.