Tuesday, 6 August 2013

           

Creating Tic-Tac-Toe with C# - 

                                                                                                                           

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.






Form1 Coding

double click the 2-Player button and write this code:
1
2
3
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 Dockproperty 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 theirRowSpan 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: resetButtonxLabel(blue), oLabel(red), backButton. We will use these names in our code.
  • Form2 Coding

    Declarations

    ?
    1
    2
    3
    4
    5
    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

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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

    ?
    1
    2
    3
    4
    5
    6
    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)

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    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

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    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

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    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?

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    private void resetVariables()
            {
                finished = false;
                turn = 0;
                O = new bool[3, 3];
                X = new bool[3, 3];
                cells = new bool[3, 3];
    counter=0;
            }
    Now we still have to write five helper methods, that we used earlier but we didn't write their codes. 


    Testing application

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