Wednesday, September 12, 2012

Creating Tic-Tac-Toe with C# - Part 1

Today we'll start a new tutorial about creating the Tic Tac Toe game, or XO game.
Open visual studio, create a new windows form application project, name it Tic Tac Toe or something..

Right now we are going to use only 2 forms.
create Tic Tac Toe gameTo add another form, right click on your project, select Add, then choose Windows Form.

a new form with the name of Form2 will appear. In this form we are going to place the game.
you may ask but Form1 for what? we will create a menu with two buttons, to choose between 2-Player mode or 1-player vs computer.

In this part of the tutorial, we will build the 2-Player mode.

create Tic Tac Toe game

Form1 design


we only need two buttons, to select the game mode.
okay, this form will look something like this:
I used a TableLayoutPanel to centralize the buttons. Click to see this tutorial if you're not sure how to use it.







Form1 Coding

double click the 2-Player button and write this code:
Form2 f2= new Form2();
this.Hide();
f2.Show();
This code will hide the current form, and open the second form.
I will leave the second button "Player cs PC" for the Part 2 of this tutorial.

Form2 design



create Tic Tac Toe game
  • Create a tableLayoutPanel, set the Dock property to Fill, divide it to 4 columns with percentage 25% of each, and 4 rows with the percentages: 33.33%, 16.66%, 16.66%, 33.33%.
  • Add a button with the Dock property set to Fill and an empty Text property. Copy and paste until you have 9 buttons filling the cells: (0,0) ; (0,1) ;  (0,2) ;  (1,0) ; (1,1) ; (1,2) ; (3,0) ; (3,1) ; (3,2) ; 
  • Select the 3 middle small height buttons and change their RowSpan property to 2.
  • Select all created buttons and set their Font property to: Tahoma; 36pt.
  • Fill the last column with 2 buttons and two labels as the picture above shows, change their names to: resetButton, xLabel(blue), oLabel(red), backButton. We will use these names in our code.

Form2 Coding

Declarations

        Button btn; //to get the clicked button data
        int turn/*to determine wich turn*/,counter/*for the played turns*/; 
        bool[,] X/*X player buttons*/, O/*O player buttons*/, cells/*Occupied cells*/, current/*X or O*/; //using 3x3 coordinate system
        string player; //X or O
        bool finished; // true when the game finish

Reset button and Form load

 
private void resetButton_Click(object sender, EventArgs e)
        {
           //clear buttons text property
           button1.Text =
           button2.Text =
           button3.Text =
           button4.Text =
           button5.Text =
           button6.Text =
           button7.Text =
           button8.Text =
           button9.Text =
           "";
            resetVariables();
        }

private void Form2_Load(object sender, EventArgs e)
        {
            resetVariables();
        }
you can notice that I used a helper method in the last line to reset the variables. I'm resetting variables on both events. I'm going to write the code of all helper methods after finishing the main ones.

Back button

private void backButton_Click(object sender, EventArgs e)
        {
            this.Hide();
            Form1 f1 = new Form1();
            f1.Show();
        }
This code will take us back to the menu (Form1).

Gaming buttons (9 buttons)EXPLAINED (Improved, thanks to Yahia)

private void gamePlayButtons_Click(object sender, EventArgs e)
        {
            int x,y;
            //ensure that the user is clicking a button, if yes give me its coordinate (x,y)
            //ensure that the game has not finished yet
            if (!wasClickedBefore(sender as Button, out x, out y)&&!finished)
            {
                counter ++;
                btn = (sender as Button); //the clicked button from the 9 buttons
                
                if (turn == 0)
                {
                    (sender as Button).ForeColor = Color.Blue;//changing color to Blue
                    player = "X";
                    X[x,y]=true;//the position(x,y) is occupied now by an X
                    current = X;
                }
                else
                {
                    (sender as Button).ForeColor = Color.Red;//changing color to Red
                    player = "O";
                    O[x, y] = true;//the position(x,y) is occupied now by an O
                    current = O;
                }
                (sender as Button).Text = player;//writing text property

                
                cells[x,y]=true; // this cell is no longer empty
                turn = (turn + 1) % 2; //switching turns, this will switch between 0 and 1
             //a Win occurs when at least 5 turns are played
             if(counter>=5)
                //Check for a win 
                if (Row(0) || Row(1) || Row(2) || Column(0) || Column(1) || Column(2) || Diagonals())
                {
                    //updating score
                    if(player=="X")
                        xLabel.Text=(int.Parse(xLabel.Text)+1).ToString();
                    else
                        oLabel.Text=(int.Parse(oLabel.Text)+1).ToString();

                    finished = true;//game finished
                    MessageBox.Show(string.Format("{0} Wins", player));//showing result
                }

             if (counter==9&&!finished)//It's a draw here
             {
                  finished = true;
                  MessageBox.Show("Draw");
             }

            }
        }
Now we still have to write five helper methods, that we used earlier but we didn't write their codes.

Check the win on diagonals

        private bool Diagonals()
        {
            return (
                (current[0, 0] && current[1, 1] && current[2, 2])
                ||
                (current[0, 2] && current[1, 1] && current[2, 0])
                );
        }

Check the win on a Row/Column

private bool Row(int p)
        {
            return (current[p, 0] && current[p, 1] && current[p, 2]);
        }
        private bool Column(int p)
        {
            return (current[0, p] && current[1, p] && current[2, p]);
        }

Was it clicked before?

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]);
        }

Reset Variables

private void resetVariables()
        {
            finished = false;
            turn = 0;
            O = new bool[3, 3];
            X = new bool[3, 3];
            cells = new bool[3, 3];
counter=0;
        }

Testing application

create Tic Tac Toe game
Now your 2-Player game is ready to test. It looks good right?

If you have any problems with it you can Download the solution from here.
Okay so today we've made a simple Tic Tac Toe game between two players. In the coming parts we are going to add the Player vs PC option.

>>CLICK FOR THE NEXT PART OF THIS TUTORIAL