A Grid is usually considered as a component that is used to display and manage data only. ComponentOne Studio FlexGrid for WinForms just starts from Data Management. We're going to close the gap between this theory and the practice in functional programming. Due to the fast and flexible architecture, FlexGrid can be used in a variety of applications ranging from simple display to complex operations to gaming.

Designing Tic-Tac-Toe in FlexGrid for WinForms

If you haven't played Tic-Tac-Toe, here's a description from Wikipedia: Tic-Tac-Toe (also known as Noughts and crosses or Xs and Os) is a paper and pencil game for two players, X and O, who take turns marking the spaces in a 3×3 grid. The player who succeeds in placing three of their marks in a horizontal, vertical, or diagonal row wins the game. TicTacToe

Exciting to see how this can be accomplished using FlexGrid! After all, it's a flexible Grid.

We need to implement two things when creating the game: the game user interface and the game logic.

The Game User Interface: Make it pretty!

The first thing to consider is making the grid pretty and attractive so that it feels like a game. This totally depends on the choice you make; I've used the images.

The Game Logic: How to Play, and Who Wins

For the logic to implement in a 3x3 grid, let's think about the following two use cases.

  • Moves of Player X and Player O
  • Identifying the Winner

Handling the Moves

Place O and X images alternatively on the cells of C1FlexGrid when clicked. We'll achieve this by maintaining a click count in MouseClick event of the grid. Also, store the name of the player clicked in UserData of current cell— this helps in declaring the winner.


if (e.Button == MouseButtons.Left && click % 2 != 0)  
{  
c1FlexGrid1.SetCellImage(c1FlexGrid1.Row, c1FlexGrid1.Col, Image.FromFile(@"..\\..\\Images\\O1.png"));  
turnLabel.Text = player2TextBox.Text;  
c1FlexGrid1.SetUserData(c1FlexGrid1.Row, c1FlexGrid1.Col, player1TextBox.Text);  
}  
else  
{  
c1FlexGrid1.SetCellImage(c1FlexGrid1.Row, c1FlexGrid1.Col, Image.FromFile(@"..\\..\\Images\\X.png"));  
turnLabel.Text = player1TextBox.Text;  
c1FlexGrid1.SetUserData(c1FlexGrid1.Row, c1FlexGrid1.Col, player2TextBox.Text);  
}  


Identifying the Winner

There are basically three scenarios in which a player can be declared as the winner.

  • Placing same sign in 3 contiguous rows of same column.
  • Placing same sign in 3 contiguous columns of same row.
  • Placing same signs in both the diagonals.

object userData = c1FlexGrid1.GetUserData(c1FlexGrid1.Row, c1FlexGrid1.Col);  
int j = 2;  
for (int i = 0; i < 3; i++)  
{  
if (c1FlexGrid1.GetUserData(c1FlexGrid1.Row, i) != null)  
{  
if (userData.ToString() != (c1FlexGrid1.GetUserData(c1FlexGrid1.Row, i)).ToString() && ver == true)  
{  
ver = false;  
}  
}  
else  
ver = false;  
if (c1FlexGrid1.GetUserData(i, c1FlexGrid1.Col) != null)  
{  
if (userData.ToString() != (c1FlexGrid1.GetUserData(i, c1FlexGrid1.Col)).ToString() && hor == true)  
{  
hor = false;  
}  
}  
else  
hor = false;  
if (c1FlexGrid1.Row == c1FlexGrid1.Col)  
{  
if (c1FlexGrid1.GetUserData(i, i) != null)  
{  
if (userData.ToString() != (c1FlexGrid1.GetUserData(i, i)).ToString() && dia == true)  
{  
dia = false;  
}  
}  
else  
dia = false;  
}  
if ((c1FlexGrid1.Row + c1FlexGrid1.Col) == 2)  
{  
if (j > -1)  
{  
if (c1FlexGrid1.GetUserData(i, j) != null)  
{  
if (userData.ToString() != (c1FlexGrid1.GetUserData(i, j--)).ToString() && oppDia == true)  
{  
oppDia = false;  
}  
}  
else  
oppDia = false;  
}  
}  
if (ver == false && hor == false && dia == false && oppDia == false)  
{  
break;  
}  
}  
if (ver == true)  
{  
won = true;  
if (c1FlexGrid1.Row == 0)  
h1Label.Visible = true;  
if (c1FlexGrid1.Row == 1)  
h2Label.Visible = true;  
if (c1FlexGrid1.Row == 2)  
h3Label.Visible = true;  
c1FlexGrid1.Enabled = false;  
mmb = new MyMessageBox(resetButton, true);  
mmb.MsgText = "Congrats! " + userData.ToString().ToUpper() + " Won";  
mmb.ShowDialog();  
click = 10;  
}  
else if (hor == true)  
{  
won = true;  
if (c1FlexGrid1.Col == 0)  
v1Label.Visible = true;  
if (c1FlexGrid1.Col == 1)  
v2Label.Visible = true;  
if (c1FlexGrid1.Col == 2)  
v3Label.Visible = true;  
c1FlexGrid1.Enabled = false;  
mmb = new MyMessageBox(resetButton, true);  
mmb.MsgText = "Congrats! " + userData.ToString().ToUpper() + " Won";  
mmb.ShowDialog();  
click = 10;  
}  
else if (c1FlexGrid1.Row == c1FlexGrid1.Col && dia == true)  
{  
won = true;  
lineShape2.Visible = true;  
c1FlexGrid1.SendToBack();  
lineShape2.BringToFront();  
c1FlexGrid1.Enabled = false;  
mmb = new MyMessageBox(resetButton, true);  
mmb.MsgText = "Congrats! " + userData.ToString().ToUpper() + " Won";  
mmb.ShowDialog();  
click = 10;  
}  
else if ((c1FlexGrid1.Row + c1FlexGrid1.Col) == 2 && oppDia == true)  
{  
won = true;  
lineShape1.Visible = true;  
c1FlexGrid1.SendToBack();  
lineShape1.BringToFront();  
c1FlexGrid1.Enabled = false;  
mmb = new MyMessageBox(resetButton, true);  
mmb.MsgText = "Congrats! " + userData.ToString().ToUpper() + " Won";  
mmb.ShowDialog();  
click = 10;  
}  
click++;  
}  

Enjoy! And while you're at it, try BubbleSmash in Chart for WinForms! We're interested in knowing if you've ever created any such game using FlexGrid. Let us know! Download Source Code