Introduction
Image processing and games programming may be the most technically challenging job that a programmer can have. The top level programs may require the best from both programmer and computer. Tic-tac-toe is a simple game that makes it easy to build algorithms for the computer to play its own move. In this article, a interactive webcam based Tic Tac Toe game is developed. Program in coded in C# .NET using AForge .NET Framework for certain image processing tasks and image acquisition.
Webcam in Application
The first step would be getting video feed from webcam within our program. We can use AForge .NET Framework for accomplishing this. Image acquisition is simple and pretty fast using AForge .NET Framework. Check out the code snippet below:
private void getCamList()
{
try
{
videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
comboBox1.Items.Clear();
if (videoDevices.Count == 0)
throw new ApplicationException();
DeviceExist = true;
foreach (FilterInfo device in videoDevices)
{
comboBox1.Items.Add(device.Name);
}
comboBox1.SelectedIndex = 0; }
catch (ApplicationException)
{
DeviceExist = false;
comboBox1.Items.Add("No capture device on your system");
}
}
private void rfsh_Click(object sender, EventArgs e)
{
getCamList();
}
private void start_Click(object sender, EventArgs e)
{
if (start.Text == "&Start")
{
if (DeviceExist)
{
videoSource =
new VideoCaptureDevice(videoDevices[comboBox1.SelectedIndex].MonikerString);
videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
CloseVideoSource();
videoSource.Start();
label2.Text = "Device running...";
start.Text = "&Stop";
}
else
{
label2.Text = "Error: No Device selected.";
}
}
else
{
if (videoSource.IsRunning)
{
timer1.Enabled = false;
CloseVideoSource();
label2.Text = "Device stopped.";
start.Text = "&Start";
}
}
}
private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Bitmap img = (Bitmap)eventArgs.Frame.Clone();
pictureBox1.Image = img;
}
private void CloseVideoSource()
{
if (!(videoSource == null))
if (videoSource.IsRunning)
{
videoSource.SignalToStop();
videoSource = null;
}
}
Think of video as a continuous stream of images, for real time image processing we need to process each and every image captured by the webcam. I'm getting an average of 7 fps within my application. More the fps, more smoothly your program will run.
Design and GUI
As you can see in the picture above, I've created a very basic design for Tic Tac Toe using GDI+ of C# .NET.
Laser Detection & Gameplay
The program searches for the brightest red blob in webcam's field of views. We can do so by using two of the filters defined in AForge .NET Framework.
- Color filter to filter out everything except red laser light.
- Blob Counter to retrieve the position of laser dot or red blob within image.
ColorFiltering filter = new ColorFiltering();
filter.Red = new IntRange(254, 255);
filter.Green = new IntRange(0, 240);
filter.Blue = new IntRange(0, 240);
Bitmap tmp = filter.Apply(image);
IFilter grayscale = new GrayscaleBT709(); tmp = grayscale.Apply(tmp);
BitmapData bitmapData = tmp.LockBits(new Rectangle(0, 0, image.Width, image.Height),
ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
blobCounter blobCounter = new BlobCounter(); blobCounter.ProcessImage(bitmapData); blobCounter.ObjectsOrder = ObjectsOrder.Size; Rectangle[] rects = blobCounter.GetObjectsRectangles(); tmp.UnlockBits(bitmapData);
tmp.Dispose();
if (rects.Length != 0)
{
backpoint = GetCenter(rects[0]); DrawLines(ref image, backpoint); }
After laser has been detected, the program keeps track on movement of laser dot and once laser is turned off, it places the user's move within that grid. To understand this, imagine a tic tac toe board with nine different grids as shown in the image below:
The algorithm is designed so that it splits every frame from webcam into nine equal rectangles depicting nine different grids of tic tac toe game. User move is placed within grid in which laser light is turned off. If you don't have laser light or you can't visualize this program, then check out the video at YouTube. For code optimization, we can further add filters before playing any move like checking grid is empty and not occupied by cross or zero, we can also add some pause or sleep so that before program could confirm that there is no laser light within webcam view.
Algorithm For Tic Tac Toe
I tried to implement AI the best way I could, even with a long code. Algorithms are designed with humanistic approach to play tic tac tic. It tries to win the game at first, preventing the other player from winning, and then tries to make a move avoiding "traps" and putting two computer pieces in a row. If none of this is possible, a random move is made.
using System;
namespace WebcamTicTacToe
{
class ZeroCross
{
public bool winner_comp = false; public bool winner_you = false; public bool tie = false; private int[] zeros = { 0, 0, 0, 0, 0 }; private int[] crosses = { 0, 0, 0, 0, 0 }; private int countero; private int counterx; public int MakeAMove(int MyMove) {
zeros[countero] = MyMove; countero++;
if (counterx == 0) {
int rand_move = RandomMove();
crosses[counterx] = rand_move;
counterx++;
return rand_move;
}
else
{
int[,] Pattern = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 },
{ 1, 4, 7 }, { 2, 5, 8 }, { 3, 6, 9 }, { 1, 5, 9 }, { 7, 5, 3 } };
int Compmove = 0;
int FinalMove = 0;
int winning_Move = 0;
for (int i = 0; i < 8; i++)
{
int oCounter = 0;
int xCounter = 0;
int Incase = 0;
for (int j = 0; j < 3; j++)
{
if (CrossSeek(Pattern[i, j]))
{
xCounter++;
}
else if (ZeroSeek(Pattern[i, j]))
{
oCounter++;
}
else
{
Incase = Pattern[i, j];
}
}
if (oCounter == 3)
{
winner_you = true;
return 0;
}
else if (xCounter == 2 && Incase != 0)
{
winning_Move = Incase;
}
else if (oCounter == 2 && Incase != 0)
{
Compmove = Incase;
}
else if (oCounter == 0 && xCounter == 1)
{
if (Compmove == 0)
{
Compmove = Incase;
}
}
else if (Incase != 0)
{
FinalMove = Incase;
}
}
if (winning_Move != 0)
{
crosses[counterx] = winning_Move;
counterx++;
winner_comp = true;
return winning_Move;
}
if (Compmove != 0)
{
crosses[counterx] = Compmove;
counterx++;
if (counterx == 5 || countero == 5)
{
winner_you = false;
winner_comp = false;
tie = true;
}
return Compmove;
}
if (FinalMove != 0)
{
crosses[counterx] = FinalMove;
counterx++;
if (counterx == 5 || countero == 5)
{
tie = true;
}
return FinalMove;
}
tie = true;
return 0;
}
}
public int CompFirstTurn()
{
int CompMove = RandomMove();
crosses[counterx] = CompMove;
counterx++;
return CompMove;
}
public bool GetWinner()
{
if (winner_comp || winner_you || tie)
{
return true;
}
return false;
}
public bool ZeroSeek(int zero)
{
for (int i = 0; i < countero; i++)
{
if (zeros[i] == zero)
{
return true;
}
}
return false;
}
public bool CrossSeek(int cross)
{
for (int i = 0; i < counterx; i++)
{
if (crosses[i] == cross)
{
return true;
}
}
return false;
}
private int RandomMove()
{
Random random = new Random();
int CompMove;
bool truth = false;
do
{
CompMove = random.Next(1, 10);
if (zeros[0] == CompMove || crosses[0] == CompMove)
{
truth = true;
}
else
{
truth = false;
}
}
while (truth);
return CompMove;
}
}
}
Using the Program
Well, the program needs a laser light and a webcam streaming images at 640 X 420, you can modify the source code provided in this article to match with your webcam's resolution.
I've added AI within the game for smooth gameplay even if your machine is not high end and it streams images at low frames per second. The program will try to predict the most probable move that you are uptop and will place it automatically even if your laser pointer is near it.
Conclusion
We have reached the end of this article. I might update this program to add more optimization for best game play. However, for now, have fun with it! You can find some videos of this application on my
blog. You can also easily modify the code to make this program do much more than just playing tic tac toe. Have fun!
History
- 1st December, 2009: Initial post