In
the previous part of this tutorial, we created the
Tic Tac Toe game for two players.
Now in
Part-2 we will add the option to let the user Play against the computer.
So open your project and let's continue building..
Create a new form
Add a new Form to your project.
Leave its name to
Form3, If you don't know how to add a new form check this:
Creating Tic-Tac-Toe with C# - Part 1
Design
Add
buttons,
labels,
radioButtons to make it look close to the picture on the right.
Naming:
change the name of your created buttons and radioButtons to:
XButton,
OButton,
easyRB,
normalRB, backButton.
We are going to use these names in our code later..
You can customize the design as you want, but here I just want to make a practical game, i'm not a Designer.
I forgot to change the
Text property of the form, change it to
Tic Tac Toe or something else...
Now go to
Form2 Design, select the
tableLayoutPanel1 copy it to your clipboard, then paste it in
Form3 Design.
The form will look like the second picture.
Now look at the properties window, and find the
Visible property, set it to
False.
Also change the button text from "
Reset" to "
Play again", it makes more sense, and its name to
playAgainButton.
This will hide the game until the user select one of the two Buttons created previously.
In this part, I'm going to write only the Easy difficulty mode.
Coding
Declare some variables in the class of
Form3
bool[,] X, O;
string player;
bool finished; // true when the game finish
int difficulity;
string ButtonsIndexs; //Indexs of remaining buttons
int x, y; //coordinate of button
Random rnd;
Lets write some helper methods now.
Reset Variables
private void resetVars()
{
ButtonsIndexs = "123456789";
finished = false;
rnd = new Random();
difficulity = 0;
O = new bool[3, 3];
X = new bool[3, 3];
}
Writing on a Button
private void Write(string p, Button targetButton)
{
if (p == "O")
{
targetButton.ForeColor = Color.Red;
O[x, y] = true; //the place (x,y) is occupied by an 'O'
}
else
{
targetButton.ForeColor = Color.Blue;
X[x, y] = true; //the place (x,y) is occupied by an 'X'
}
targetButton.Text = p; //Writing X or O
//Removing the index of the clicked button from ButtonIndexs
if (targetButton == button1)
ButtonsIndexs=ButtonsIndexs.Remove(ButtonsIndexs.IndexOf('1'), 1);
if (targetButton == button2)
ButtonsIndexs=ButtonsIndexs.Remove(ButtonsIndexs.IndexOf('2'), 1);
if (targetButton == button3)
ButtonsIndexs=ButtonsIndexs.Remove(ButtonsIndexs.IndexOf('3'), 1);
if (targetButton == button4)
ButtonsIndexs=ButtonsIndexs.Remove(ButtonsIndexs.IndexOf('4'), 1);
if (targetButton == button5)
ButtonsIndexs=ButtonsIndexs.Remove(ButtonsIndexs.IndexOf('5'), 1);
if (targetButton == button6)
ButtonsIndexs=ButtonsIndexs.Remove(ButtonsIndexs.IndexOf('6'), 1);
if (targetButton == button7)
ButtonsIndexs=ButtonsIndexs.Remove(ButtonsIndexs.IndexOf('7'), 1);
if (targetButton == button8)
ButtonsIndexs=ButtonsIndexs.Remove(ButtonsIndexs.IndexOf('8'), 1);
if (targetButton == button9)
ButtonsIndexs=ButtonsIndexs.Remove(ButtonsIndexs.IndexOf('9'), 1);
}
Easy difficulity, Computer turn
private void EasyPCWrite(string p)
{
// a Random button index (to chose a random free button)
int index = int.Parse(ButtonsIndexs[rnd.Next(ButtonsIndexs.Length)].ToString());
switch (index)
{
case 1: x = y = 0; Write(p, button1); break;
case 2: x = 0; y = 1; Write(p, button2); break;
case 3: x = 0; y = 2; Write(p, button3); break;
case 4: x = 1; y = 0; Write(p, button4); break;
case 5: x = 1; y = 1; Write(p, button5); break;
case 6: x = 1; y = 2; Write(p, button6); break;
case 7: x = 2; y = 0; Write(p, button7); break;
case 8: x = 2; y = 1; Write(p, button8); break;
case 9: x = 2; y = 2; Write(p, button9); break;
}
}
Normal difficulty, Computer turn
private void NormalPCWrite(string p)
{
//Coming in Part 3
}
Checking if any diagonal wins
private bool Diagonals(bool[,] current)
{
return (
(current[0, 0] && current[1, 1] && current[2, 2])
||
(current[0, 2] && current[1, 1] && current[2, 0])
);
}
Checking if any row wins
private bool Row(int p, bool[,] current)
{
return (current[p, 0] && current[p, 1] && current[p, 2]);
}
Checking if any column wins
private bool Column(int p, bool[,] current)
{
return (current[0, p] && current[1, p] && current[2, p]);
}
Checking for win or Draw
private bool CheckForWinOrDraw(bool[,] current)
{
if (Row(0, current) || Row(1, current) || Row(2, current) || Column(0, current) || Column(1, current) || Column(2, current) || Diagonals(current))
{
//updating score
if (current == X)
xLabel.Text = (int.Parse(xLabel.Text) + 1).ToString();
else
oLabel.Text = (int.Parse(oLabel.Text) + 1).ToString();
//game finished
finished = true;
MessageBox.Show(string.Format("{0} Wins", (ButtonsIndexs.Length%2==0)?"X":"O"));//showing result
}
else
{
if (ButtonsIndexs=="")
{
//game finished
finished = true;
MessageBox.Show("Draw");
}
}
return finished;
}
Checking if the button was clicked before (by PC or player)
private bool wasClickedBefore(Button button, out int x, out int y)
{
x = y = 0;
switch (button.Name)
{
case "button1": x = 0; y = 0; break;
case "button2": x = 0; y = 1; break;
case "button3": x = 0; y = 2; break;
case "button4": x = 1; y = 0; break;
case "button5": x = 1; y = 1; break;
case "button6": x = 1; y = 2; break;
case "button7": x = 2; y = 0; break;
case "button8": x = 2; y = 1; break;
case "button9": x = 2; y = 2; break;
}
return (X[x, y] || O[x, y]);
}
only one helper method left, it's
the computer turn in Normal mode. I will leave it to the third part of this tutorial.
Now lets write the code to the buttons.
Play again button event
private void playAgianButton_Click(object sender, EventArgs e)
{
resetVars();
button1.Text =
button2.Text =
button3.Text =
button4.Text =
button5.Text =
button6.Text =
button7.Text =
button8.Text =
button9.Text =
"";
if (player == "O") player = "X";
else
{
player = "O";
if (difficulity == 0)
EasyPCWrite("X");
else
NormalPCWrite("X");
}
}
Game buttons Click(the 9 buttons)
private void gameButtons_Click(object sender, EventArgs e)
{
if(!wasClickedBefore(sender as Button,out x, out y)&&!finished)
{
if(player=="O")
{
//The user turn
Write("O",sender as Button);
if (!CheckForWinOrDraw(O))
{
//PC turn
if (difficulity == 0)
EasyPCWrite("X");
else
NormalPCWrite("X");
CheckForWinOrDraw(X);
}
}
else
{
//The user turn
Write("X",sender as Button);
if(!CheckForWinOrDraw(X))
{
//PC turn
if(difficulity==0)
EasyPCWrite("O");
else
NormalPCWrite("O");
CheckForWinOrDraw(O);
}
}
}
}
The back button (second one)
private void back_Click(object sender, EventArgs e)
{
easyRB.Checked = true;
playAgainButton.PerformClick();
xLabel.Text = oLabel.Text = "0";
tableLayoutPanel1.Visible = false;
this.Size = new Size(229, 300);
}
Radio buttons checked
private void easyRB_Click(object sender, EventArgs e)
{
difficulity = 0; //Easy level
}
private void normalRB_CheckedChanged(object sender, EventArgs e)
{
difficulity = 1; //Normal Level
}
Main buttons (XButton and OButton)
private void mainButtons(object sender, EventArgs e)
{
player = (sender as Button).Text; //user choice, X or O
this.Size = new Size(382, 300); //changes form size
tableLayoutPanel1.Visible = true;
if (difficulity == 0)
if (player == "O")
EasyPCWrite("X");
else
return;
else
if (player == "O")
NormalPCWrite("X");
}
Back button
private void backButton_Click(object sender, EventArgs e)
{
Form1 f1 = new Form1();
this.Hide();
f1.Show();
}
Form3_Load event
private void Form3_Load(object sender, EventArgs e)
{
resetVars();
}
Last step, go to
Form1 and double click the
PC vs Player button..
Player vs PC button
private void playerVsPC_Click(object sender, EventArgs e)
{
Form3 f3 = new Form3();
this.Hide();
f3.Show();
}
We've created today the
Easy PC mode of player vs PC option in
Tic Tac Toe game.
It's almost done, Last part of this tutorial will include the
Normal PC mode, and some other final touches for your game to be ready!
Stay tuned, if you have any question post it to
my Facebook page and I'll try to help, see you later.
>>CLICK FOR THE NEXT PART OF THIS TUTORIAL