.NET Tic-Tac-Toe Example

This Tic-Tac-Toe game is the simpliest example of a .NET application. It contains one source file. Compare it to the MFC Tic-Tac-Toe example and WinAPI Tic-Tac-Toe example. Download the source code: DOTNETTICTACTOE.ZIP

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text;

namespace TicTacToe
{
	class TicTacToe : Form
	{
		protected int[] m_nGameGrid = new int[9];
		protected int m_nNextChar;
		protected const int EX = 1;
		protected const int OH = 2;
		protected Rectangle[] m_rcSquares = {
			new Rectangle(16,16,96,96),
			new Rectangle(128,16,96,96),
			new Rectangle(240,16,96,96),
			new Rectangle(16,128,96,96),
			new Rectangle(128,128,96,96),
			new Rectangle(240,128,96,96),
			new Rectangle(16,240,96,96),
			new Rectangle(128,240,96,96),
			new Rectangle(240,240,96,96)};

		static void Main()
		{
			Application.Run(new TicTacToe());
		}
		public TicTacToe()
		{
			Text = "TicTacToe -L R M mouse buttons";
			Width = 366;
			Height = 382;
			this.FormBorderStyle = FormBorderStyle.Fixed3D;
			this.MouseClick += new MouseEventHandler(TicTacToe_MouseClick);
			ResetGame();
		}
		protected override void OnPaint(PaintEventArgs e)
		{
			base.OnPaint(e);
			DrawBoard(e.Graphics);
		}
		protected int GetRectID(Point pt)
		{
			for (int i = 0; i < 9; i++)
			{
				if (pt.X > m_rcSquares[i].Left && pt.X < m_rcSquares[i].Right &&
					pt.Y > m_rcSquares[i].Top && pt.Y < m_rcSquares[i].Bottom)
					return i;
			}
			return -1;
		}
		protected void DrawBoard(Graphics g)
		{
			Pen pn = new Pen(Color.Black, 16);
			g.DrawLine(pn, 120, 16, 120, 336);
			g.DrawLine(pn, 232, 16, 232, 336);
			g.DrawLine(pn, 16, 120, 336, 120);
			g.DrawLine(pn, 16, 232, 336, 232);

			for (int i = 0; i < 9; i++)
			{
				if (m_nGameGrid[i] == EX)
					DrawX(i);
				else if (m_nGameGrid[i] == OH)
					DrawO(i);
			}
		}
		protected void DrawX(int nPos)
		{
			using (Graphics g = CreateGraphics())
			{
				Pen pn = new Pen(Color.Red, 16);
				Rectangle rect = m_rcSquares[nPos];
				rect.Inflate(-16, -16);
				g.DrawLine(pn, rect.Left, rect.Top, rect.Right, rect.Bottom);
				g.DrawLine(pn, rect.Left, rect.Bottom, rect.Right, rect.Top);
			}
		}
		protected void DrawO(int nPos)
		{
			using (Graphics g = CreateGraphics())
			{
				Pen pn = new Pen(Color.Blue, 16);
				Rectangle rect = m_rcSquares[nPos];
				rect.Inflate(-16, -16);
				g.DrawEllipse(pn, rect);
			}
		}
		protected void CheckForGameOver()
		{
			int nWinner = IsWinner();

			if (nWinner != 0)
			{
				string str = (nWinner == EX) ? "X wins!" : "O wins!";
				MessageBox.Show(str, "Game Over", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				ResetGame();
			}
			else if (IsDraw())
			{
				MessageBox.Show("It's a draw!", "Game Over", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				ResetGame();
			}
		}
		protected int IsWinner()
		{
			int[,] nPattern = {
				{0,1,2},
				{3,4,5},
				{6,7,8},
				{0,3,6},
				{1,4,7},
				{2,5,8},
				{0,4,8},
				{2,4,6}
				};
			for (int i = 0; i < 8; i++)
			{
				if ((m_nGameGrid[nPattern[i, 0]] == EX) &&
					(m_nGameGrid[nPattern[i, 1]] == EX) &&
					(m_nGameGrid[nPattern[i, 2]] == EX))
					return EX;
				if ((m_nGameGrid[nPattern[i, 0]] == OH) &&
					(m_nGameGrid[nPattern[i, 1]] == OH) &&
					(m_nGameGrid[nPattern[i, 2]] == OH))
					return OH;
			}
			return 0;
		}
		protected bool IsDraw()
		{
			for (int i = 0; i < 9; i++)
			{
				if(m_nGameGrid[i] == 0)
					return false;
			}
			return true;
		}
		protected void ResetGame()
		{
			m_nNextChar = EX;
			for (int i = 0; i < 9; i++)
			{
				m_nGameGrid[i] = 0;
			}
			Invalidate();
		}
		void TicTacToe_MouseClick(object sender, MouseEventArgs e)
		{
			if (e.Button == MouseButtons.Left)
			{
				if (m_nNextChar != EX)
					return;
				int nPos = GetRectID(new Point(e.X, e.Y));
				if (nPos == -1 || m_nGameGrid[nPos] != 0)
					return;
				m_nGameGrid[nPos] = EX;
				m_nNextChar = OH;
				DrawX(nPos);
				CheckForGameOver();
			}
			else if (e.Button == MouseButtons.Right)
			{
				if (m_nNextChar != OH)
					return;
				int nPos = GetRectID(new Point(e.X, e.Y));
				if (nPos == -1 || m_nGameGrid[nPos] != 0)
					return;
				m_nGameGrid[nPos] = OH;
				m_nNextChar = EX;
				DrawO(nPos);
				CheckForGameOver();
			}
			else if (e.Button == MouseButtons.Middle)
			{
				ResetGame();
			}
		}
	}
}