Showing posts with label how to create tic tac toe. Show all posts
Showing posts with label how to create tic tac toe. Show all posts

Saturday, September 15, 2012

Creating Tic-Tac-Toe with C# - Part 3 (Final part)

So now we will finalize our project.
In part 2, we created the computer role in the Tic Tac Toe game, but as a dumb.
So now we are going to program the smart playing algorithm in C#.
We will consider two main points in the algorithm:

  1. Do we have a winning play? if yes lets play it and win! No? proceed to step 2.
  2. Check if the opponent has a winning move, block it if yes, continue to step 3 if no.
  3. Play like our old friend from part 2, yes it's the dumb.


HELPER METHODS

the NormalPCWrite method is not that easy, so we are going to create four helper methods.

Get Coordinates

        private void getCoordinates(int p, out int x, out int y)
        {//change the variables x and y to the correct coordinate
            switch (p)
            {
                case 1: x = 0; y = 0; break;
                case 2: x = 0; y = 1; break;
                case 3: x = 0; y = 2; break;
                case 4: x = 1; y = 0; break;
                case 5: x = 1; y = 1; break;
                case 6: x = 1; y = 2; break;
                case 7: x = 2; y = 0; break;
                case 8: x = 2; y = 1; break;
                default: x = 2; y = 2; break;
            }
        }

Clicked (+1 overload)

private bool clicked(int index)
        {//true if it was clicked, false if it's still clickable
            return (ButtonsIndexs.IndexOf(index.ToString()) == -1);
        }
private bool clicked(int index,string p)
        {//checks if "p" is written on the button with index "index"
            int a,b;
            switch(index){
                case 1:a=0;b=0;break;
                case 2:a=0;b=1;break;
                case 3:a=0;b=2;break;
                case 4:a=1;b=0;break;
                case 5:a=1;b=1;break;
                case 6:a=1;b=2;break;
                case 7:a=2;b=0;break;
                case 8:a=2;b=1;break;
                default:a=2;b=2;break;
                    }
            if (p == "X")
                return (X[a, b]);
            return (O[a, b]);
        }

Write_buttonIndex

private void Write_buttonIndex(int index, string toWrite)
        {//Writing 'toWrite' in a button by knowing its index p
            switch (index)
            {
                case 1: Write(toWrite, button1); break;
                case 2: Write(toWrite, button2); break;
                case 3: Write(toWrite, button3); break;
                case 4: Write(toWrite, button4); break;
                case 5: Write(toWrite, button5); break;
                case 6: Write(toWrite, button6); break;
                case 7: Write(toWrite, button7); break;
                case 8: Write(toWrite, button8); break;
                default: Write(toWrite, button9); break;
            } 
        }

check

        private bool check(int i, int k, string toCheck,string toWrite)
        {
            //k=1 for rows, k=3 for columns, k=5-i for diagonals
            string P = (toWrite == "X") ? "O" : "X";
            if ((clicked(i,toCheck) && clicked(i+k,toCheck) && !clicked(i + k + k)))
            {
                getCoordinates(i + k + k, out x, out y);
                Write_buttonIndex(i + k + k, toWrite);
                return true;
            }
            if ((clicked(i,toCheck) && clicked(i+k+k,toCheck) && !clicked(i + k)))
            {
                getCoordinates(i + k, out x, out y);
                Write_buttonIndex(i + k, toWrite);
                return true;
            }
            if ((clicked(i+k,toCheck) && clicked(i+k+k,toCheck) && !clicked(i)))
            {
                getCoordinates(i, out x, out y);
                Write_buttonIndex(i, toWrite);
                return true;
            }
            return false;
        }

Please read the helper methods carefully to understand well how they work. Now Finally lets write the NormalPCWrite method!

Normal level method

private void NormalPCWrite(string p)
        { 
            string q = (p == "X") ? "O" : "X";
            //Lets check if we can win
            if (!check(1, 1, p, p))
                if (!check(4, 1, p, p))
                    if (!check(7, 1, p, p))
                        if (!check(1, 3, p, p))
                            if (!check(2, 3, p, p))
                                if (!check(3, 3, p, p))
                                    if (!check(1, 4, p, p))
                                        if (!check(3, 2, p, p))
                                            if (!check(1, 1, q, p))
                                                //It seems that we can't, let's defend
                                                if (!check(4, 1, q, p))
                                                    if (!check(7, 1, q, p))
                                                        if (!check(1, 3, q, p))
                                                            if (!check(2, 3, q, p))
                                                                if (!check(3, 3, q, p))
                                                                    if (!check(1, 4, q, p))
                                                                        if(!check(3, 2, q, p))
                                                                            //play randomly
                                                                        EasyPCWrite(p);   
        }
Note: this is not the best playing, as we can create a more smarter algorithm, which will avoid and even try to create TRAPS. Maybe you can do it? try to add one more difficulty, the Unbeatable.

For the best performance, please edit some of our previously created methods.

EDIT: resetVars()

private void resetVars()
        {
            ButtonsIndexs = "123456789";
            finished = false;
            rnd = new Random();
            O = new bool[3, 3];
            X = new bool[3, 3];
        }

EDIT: Form3_Load()

        private void Form3_Load(object sender, EventArgs e)
        {
            difficulity = 0;
            resetVars();
        }

EDIT: back_Click()

private void back_Click(object sender, EventArgs e)
        {
            if (difficulity == 0)
                easyRB.Checked = true;
            else
                normalRB.Checked = true;
            playAgainButton.PerformClick();
            xLabel.Text = oLabel.Text = "0";
            tableLayoutPanel1.Visible = false;
            this.Size = new Size(229, 300);
        }
If you are working  with me, you probably noticed while debugging, that if you click the close button (X) of the form, the debugger doesn't stop.
That's because you are closing a single form, while previous ones are hidden.
To solve this and to end the application process when the user click the (X) button, go to each form, look for an event called Form closing. double click it and add this line of code:
Application.Exit();
Finally we are done! I wish you enjoyed this tutorial, go play some Tic Tac Toe now ;) see you later..

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