DEV Community

loading...
Cover image for How to create a Tic Tac Toe game in CLI/C++ in Windows

How to create a Tic Tac Toe game in CLI/C++ in Windows

panquesito7 profile image David Leal ・Updated on ・12 min read

Hello everyone. Hope you're doing fine today!
Today we're going to see how to create a Tic Tac Toe game in CLI/C++ using Visual Studio 2019!

To start, let's first check if we have Visual Studio 2019.
If you don't, then go to the Visual Studio website.

If you already have Visual Studio installed, skip to Getting started.

Installing Visual Studio 2019

Download the Visual Studio 2019 Community Edition.
After the download has completed, open the installer, and follow the steps.

When it has almost finished, it'll appear a dialog where you can select all the components you want to work with (e.g.: C++ game development, mobile development, Linux C++ development, etc.).

Select components in Visual Studio

You can scroll down and see more and more components that you will use. Please note that the more stuff you add the more space the program will require.

Now, choose the Desktop development with .NET and Desktop development with C++.
Next, go to the Individual components sidebar.

Individual components sidebar

Search for CLI, and you'll see various options here:

CLI search

Choose the one that has a checkmark on it (it may be named a bit differently as I am in the Spanish language).
Once you got all things set up, click on the Install button and wait while it installs.

Now that we got everything set up, we can start coding!

Getting started

Once you have Visual Studio open, we'll see something like this:

Visual Studio

We'll choose up the "Create project" option.

"Create project" option

Next, we'll see various options to create our project (templates, empty projects, etc.).

Available project templates

If you search out for "clr", you'll see some options like this:

"clr" search in Visual Studio

Choose the one that says "Empty CLR project (.NET Framework).

Empty CLR project (.NET Framework)

Next, you'll see something up like this:

Finish setting up your new project

Choose a directory where'd you like to have it. Choose the .NET Framework version (I recommend using the latest one in the strip menu).
Choose a name for your project. I recommend using TicTacToe, as in many parts of the code it'll depend on the project's name.
Now click on the "Create" button! Wait while the project creates itself (note that it may take some minutes depending on your PC's hardware).

Coding and making the game

Once you have the project/solution opened, click on "Project", then "Add new item".

Add new item

Next, it'll appear something up like this:
Add new item (choose an item)

Click on the one that says "UI", then click on the "Windows Form" option.

"Windows Form" option

Choose a name for the file. I recommend using TicTacToe.h. Then click on the "Add" button. That's it. You have the Windows Form added. Woo-hoo!

At first, it may display an error. Try to re-open the .h file.
If that doesn't fix it, close the whole project and the program, and re-open it. In the worst cases, restart your PC.

In the directory where you saved your project, go to the TicTacToe folder.
You may see various files over there. Open TicTacToe.cpp and TicTacToe.h

In TicTacToe.cpp, replace the whole code with this one:

#include "TicTacToe.h"

[System::STAThread]
void main(array <System::String^>^ args) {
    System::Windows::Forms::Application::EnableVisualStyles();
    System::Windows::Forms::Application::SetCompatibleTextRenderingDefault(false);

    TicTacToe::TicTacToe form;
    System::Windows::Forms::Application::Run(% form);
}
Enter fullscreen mode Exit fullscreen mode

Now go into the TicTacToe.h file.
We'll start building the core of the game. πŸ˜‰

Replace the code in TicTacToe.h with this one.

The Gist has the main parts of the code: the buttons, menu strips, labels, etc..

Don't compile the code yet! It'll throw lots of errors.

At the end of the code, you'll see this line has #pragma endregion in it. Before that, add the following code:

uint16_t turn = 0; // Whether to choose if the X or the O will place.
bool match_ended = false; // If the match has ended or not.
Enter fullscreen mode Exit fullscreen mode

Here, we've just created two variables: one: choose who will place, whether the O or the X; two: has the match ended or not?

We'll now be creating the functionality of the "Start game!" button.
The button is supposed to remove itself and add the other buttons so you can click on them and an "O" or "X" will appear.

After the code #pragma endregion, add the following code:

    private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { // "Start game!" button
        this->button1->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 8.25F));
        this->button1->Location = System::Drawing::Point(80, 58);
        this->button1->Name = L"button1";
        this->button1->Size = System::Drawing::Size(0, 0);
        this->button1->Text = L"";

        /**
         * @brief Initialize buttons when clicking "Start game!"
         */

         // 
         // button11 ("Restart game" button)
         // 
        this->button11->Location = System::Drawing::Point(184, 149);
        this->button11->Name = L"button11";
        this->button11->Size = System::Drawing::Size(88, 31);
        this->button11->TabIndex = 9;
        this->button11->Text = L"Restart game";
        this->button11->UseVisualStyleBackColor = true;
        this->button11->Click += gcnew System::EventHandler(this, &TicTacToe::restart_game);

         // 
         // button2
         // 
        this->button2->Location = System::Drawing::Point(80, 50);
        this->button2->Name = L"button2";
        this->button2->Size = System::Drawing::Size(31, 25);
        this->button2->TabIndex = 2;
        this->button2->Text = L" ";
        this->button2->UseVisualStyleBackColor = true;
        this->button2->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
        // 
        // button3
        // 
        this->button3->Location = System::Drawing::Point(117, 50);
        this->button3->Name = L"button3";
        this->button3->Size = System::Drawing::Size(31, 25);
        this->button3->TabIndex = 3;
        this->button3->Text = L" ";
        this->button3->UseVisualStyleBackColor = true;
        this->button3->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
        // 
        // button4
        // 
        this->button4->Location = System::Drawing::Point(154, 50);
        this->button4->Name = L"button4";
        this->button4->Size = System::Drawing::Size(31, 25);
        this->button4->TabIndex = 4;
        this->button4->Text = L" ";
        this->button4->UseVisualStyleBackColor = true;
        this->button4->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
        // 
        // button5
        // 
        this->button5->Location = System::Drawing::Point(80, 81);
        this->button5->Name = L"button5";
        this->button5->Size = System::Drawing::Size(31, 25);
        this->button5->TabIndex = 5;
        this->button5->Text = L" ";
        this->button5->UseVisualStyleBackColor = true;
        this->button5->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
        // 
        // button6
        // 
        this->button6->Location = System::Drawing::Point(117, 81);
        this->button6->Name = L"button6";
        this->button6->Size = System::Drawing::Size(31, 25);
        this->button6->TabIndex = 6;
        this->button6->Text = L" ";
        this->button6->UseVisualStyleBackColor = true;
        this->button6->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
        // 
        // button7
        // 
        this->button7->Location = System::Drawing::Point(154, 81);
        this->button7->Name = L"button7";
        this->button7->Size = System::Drawing::Size(31, 25);
        this->button7->TabIndex = 7;
        this->button7->Text = L" ";
        this->button7->UseVisualStyleBackColor = true;
        this->button7->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
        // 
        // button8
        // 
        this->button8->Location = System::Drawing::Point(80, 112);
        this->button8->Name = L"button8";
        this->button8->Size = System::Drawing::Size(31, 25);
        this->button8->TabIndex = 8;
        this->button8->Text = L" ";
        this->button8->UseVisualStyleBackColor = true;
        this->button8->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
        // 
        // button9
        // 
        this->button9->Location = System::Drawing::Point(117, 112);
        this->button9->Name = L"button9";
        this->button9->Size = System::Drawing::Size(31, 25);
        this->button9->TabIndex = 9;
        this->button9->Text = L" ";
        this->button9->UseVisualStyleBackColor = true;
        this->button9->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
        // 
        // button10
        // 
        this->button10->Location = System::Drawing::Point(154, 112);
        this->button10->Name = L"button10";
        this->button10->Size = System::Drawing::Size(31, 25);
        this->button10->TabIndex = 10;
        this->button10->Text = L" ";
        this->button10->UseVisualStyleBackColor = true;
        this->button10->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
    }
Enter fullscreen mode Exit fullscreen mode

This code should do the following as in the video.
As you can see, immediately when you click the button, it removes itself and adds other buttons. The code above should do that.

Now, this is the greatest part: the code for the buttons to place an "O" or an "X"!

After the latest code you added, add the following code:

    private: System::Void button_click(System::Object^ sender, System::EventArgs^ e) { // Buttons to place O and X
        Button^ Numbers = safe_cast<Button^>(sender);

        if ((match_ended) || (Numbers->Text != " ")) { // Check if string is empty. If so, do not change anything.
            return;
        }

        if (turn == 0) {
            Numbers->Text = "O";
            Numbers->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(0)), static_cast<System::Int32>(static_cast<System::Byte>(0)),
                static_cast<System::Int32>(static_cast<System::Byte>(192)));
            Numbers->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 8.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
                static_cast<System::Byte>(0)));
            turn = 1;
        }

        else if (turn == 1) {
            Numbers->Text = "X";
            Numbers->ForeColor = System::Drawing::Color::Red;
            Numbers->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 8.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
                static_cast<System::Byte>(0)));
            turn = 0;
        }

        /**
         * @brief The system to determine if it's a match or not
         * We'll first determine if the O wins. After that, we'll check the X
         */
         //                                                                               // O O O
        if ((button2->Text == "O") && (button3->Text == "O") && (button4->Text == "O")) { //
                                                                                          //
            match_ended = true;
            label2->Text = "The O won the game!";
        }
        //                                                                                     //
        else if ((button5->Text == "O") && (button6->Text == "O") && (button7->Text == "O")) { // O O O
                                                                                               //
            match_ended = true;
            label2->Text = "The O won the game!";
        }
        //                                                                                      //
        else if ((button8->Text == "O") && (button9->Text == "O") && (button10->Text == "O")) { //
                                                                                                // O O O
            match_ended = true;
            label2->Text = "The O won the game!";
        }

        //                                                                                // O
        if ((button2->Text == "O") && (button5->Text == "O") && (button8->Text == "O")) { // O
                                                                                          // O
            match_ended = true;
            label2->Text = "The O won the game!";
        }
        //                                                                                     //   O
        else if ((button3->Text == "O") && (button6->Text == "O") && (button9->Text == "O")) { //   O
                                                                                               //   O
            match_ended = true;
            label2->Text = "The O won the game!";
        }
        //                                                                                      //     O
        else if ((button4->Text == "O") && (button7->Text == "O") && (button10->Text == "O")) { //     O
                                                                                                //     O
            match_ended = true;
            label2->Text = "The O won the game!";
        }

        //                                                                                      // O
        else if ((button2->Text == "O") && (button6->Text == "O") && (button10->Text == "O")) { //   O
                                                                                                //     O
            match_ended = true;
            label2->Text = "The O won the game!";
        }

        //                                                                                     //     O
        else if ((button4->Text == "O") && (button6->Text == "O") && (button8->Text == "O")) { //   O
                                                                                               // O
            match_ended = true;
            label2->Text = "The O won the game!";
        }

        /**
         * @brief The system to determine
         * if it's a match or not (for the X)
         * We'll determine if the X wins.
         */
         //                                                                               // X X X
        if ((button2->Text == "X") && (button3->Text == "X") && (button4->Text == "X")) { //
                                                                                          //
            match_ended = true;
            label2->Text = "The X won the game!";
        }
        //                                                                                     //
        else if ((button5->Text == "X") && (button6->Text == "X") && (button7->Text == "X")) { // X X X
                                                                                               //
            match_ended = true;
            label2->Text = "The X won the game!";
        }
        //                                                                                      //
        else if ((button8->Text == "X") && (button9->Text == "X") && (button10->Text == "X")) { //
                                                                                                // X X X
            match_ended = true;
            label2->Text = "The X won the game!";
        }

        //                                                                                // X
        if ((button2->Text == "X") && (button5->Text == "X") && (button8->Text == "X")) { // X
                                                                                          // X
            match_ended = true;
            label2->Text = "The X won the game!";
        }
        //                                                                                     //   X
        else if ((button3->Text == "X") && (button6->Text == "X") && (button9->Text == "X")) { //   X
                                                                                               //   X
            match_ended = true;
            label2->Text = "The X won the game!";
        }
        //                                                                                      //     X
        else if ((button4->Text == "X") && (button7->Text == "X") && (button10->Text == "X")) { //     X
                                                                                                //     X
            match_ended = true;
            label2->Text = "The X won the game!";
        }

        //                                                                                      // X
        else if ((button2->Text == "X") && (button6->Text == "X") && (button10->Text == "X")) { //   X
                                                                                                //     X
            match_ended = true;
            label2->Text = "The X won the game!";
        }

        //                                                                                     //     X
        else if ((button4->Text == "X") && (button6->Text == "X") && (button8->Text == "X")) { //   X
                                                                                               // X
            match_ended = true;
            label2->Text = "The X won the game!";
        }


    }
Enter fullscreen mode Exit fullscreen mode

All the code above should do:

  • We'll first check if the text is NOT empty. If so, do not change the text.
  • This code:
        if (turn == 0) {
            Numbers->Text = "O";
            Numbers->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(0)), static_cast<System::Int32>(static_cast<System::Byte>(0)),
                static_cast<System::Int32>(static_cast<System::Byte>(192)));
            Numbers->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 8.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
                static_cast<System::Byte>(0)));
            turn = 1;
        }

        else if (turn == 1) {
            Numbers->Text = "X";
            Numbers->ForeColor = System::Drawing::Color::Red;
            Numbers->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 8.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
                static_cast<System::Byte>(0)));
            turn = 0;
        }
Enter fullscreen mode Exit fullscreen mode

will first add the "O". It'll make it bold and blue.
It'll then trigger the turn ("X" will now place).

Else, if the turn is for the "X", it'll make it bold and red.
It'll then trigger the turn ("O" will now place). And so on...

  • The code:
        if ((button2->Text == "O") && (button3->Text == "O") && (button4->Text == "O")) { //
                                                                                          //
            match_ended = true;
            label2->Text = "The O won the game!";
        }
        //                                                                                     //
        else if ((button5->Text == "O") && (button6->Text == "O") && (button7->Text == "O")) { // O O O
                                                                                               //
            match_ended = true;
            label2->Text = "The O won the game!";
        }
        //                                                                                      //
        else if ((button8->Text == "O") && (button9->Text == "O") && (button10->Text == "O")) { //
                                                                                                // O O O
            match_ended = true;
            label2->Text = "The O won the game!";
        }

        //                                                                                // O
        if ((button2->Text == "O") && (button5->Text == "O") && (button8->Text == "O")) { // O
                                                                                          // O
            match_ended = true;
            label2->Text = "The O won the game!";
        }
        //                                                                                     //   O
        else if ((button3->Text == "O") && (button6->Text == "O") && (button9->Text == "O")) { //   O
                                                                                               //   O
            match_ended = true;
            label2->Text = "The O won the game!";
        }
        //                                                                                      //     O
        else if ((button4->Text == "O") && (button7->Text == "O") && (button10->Text == "O")) { //     O
                                                                                                //     O
            match_ended = true;
            label2->Text = "The O won the game!";
        }

        //                                                                                      // O
        else if ((button2->Text == "O") && (button6->Text == "O") && (button10->Text == "O")) { //   O
                                                                                                //     O
            match_ended = true;
            label2->Text = "The O won the game!";
        }

        //                                                                                     //     O
        else if ((button4->Text == "O") && (button6->Text == "O") && (button8->Text == "O")) { //   O
                                                                                               // O
            match_ended = true;
            label2->Text = "The O won the game!";
        }
Enter fullscreen mode Exit fullscreen mode

will determine who wins and if it's valid or not.
For example, it'll check for the first three buttons. If they all include the same value (all "X" or "O"), there'll be a winner, and you can no longer add more "O"'s or "X"'s.

In the video, you saw there was a "Restart game" button. Let's code it!
After the latest code you added, add the following code:

private: System::Void restart_game(System::Object^ sender, System::EventArgs^ e) {
        System::Windows::Forms::DialogResult result = MessageBox::Show(this, "Are you sure you want to end match?", "Restart game", MessageBoxButtons::YesNo, MessageBoxIcon::Exclamation);

        if (System::Windows::Forms::DialogResult::No == result)
        {
            // "No" or "Cancel" button.
        }
        else
        {
            // "Yes" button.

            match_ended = false;  // Match has been restarted, therefore it's not ended.
            turn = 0; // Make the O go first.

            label2->Text = " "; // Reset winner text to default settings.

            // 
            // button2
            // 
            this->button2->Location = System::Drawing::Point(80, 50);
            this->button2->Name = L"button2";
            this->button2->Size = System::Drawing::Size(31, 25);
            this->button2->TabIndex = 2;
            this->button2->Text = L" ";
            this->button2->UseVisualStyleBackColor = true;
            this->button2->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
            // 
            // button3
            // 
            this->button3->Location = System::Drawing::Point(117, 50);
            this->button3->Name = L"button3";
            this->button3->Size = System::Drawing::Size(31, 25);
            this->button3->TabIndex = 3;
            this->button3->Text = L" ";
            this->button3->UseVisualStyleBackColor = true;
            this->button3->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
            // 
            // button4
            // 
            this->button4->Location = System::Drawing::Point(154, 50);
            this->button4->Name = L"button4";
            this->button4->Size = System::Drawing::Size(31, 25);
            this->button4->TabIndex = 4;
            this->button4->Text = L" ";
            this->button4->UseVisualStyleBackColor = true;
            this->button4->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
            // 
            // button5
            // 
            this->button5->Location = System::Drawing::Point(80, 81);
            this->button5->Name = L"button5";
            this->button5->Size = System::Drawing::Size(31, 25);
            this->button5->TabIndex = 5;
            this->button5->Text = L" ";
            this->button5->UseVisualStyleBackColor = true;
            this->button5->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
            // 
            // button6
            // 
            this->button6->Location = System::Drawing::Point(117, 81);
            this->button6->Name = L"button6";
            this->button6->Size = System::Drawing::Size(31, 25);
            this->button6->TabIndex = 6;
            this->button6->Text = L" ";
            this->button6->UseVisualStyleBackColor = true;
            this->button6->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
            // 
            // button7
            // 
            this->button7->Location = System::Drawing::Point(154, 81);
            this->button7->Name = L"button7";
            this->button7->Size = System::Drawing::Size(31, 25);
            this->button7->TabIndex = 7;
            this->button7->Text = L" ";
            this->button7->UseVisualStyleBackColor = true;
            this->button7->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
            // 
            // button8
            // 
            this->button8->Location = System::Drawing::Point(80, 112);
            this->button8->Name = L"button8";
            this->button8->Size = System::Drawing::Size(31, 25);
            this->button8->TabIndex = 8;
            this->button8->Text = L" ";
            this->button8->UseVisualStyleBackColor = true;
            this->button8->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
            // 
            // button9
            // 
            this->button9->Location = System::Drawing::Point(117, 112);
            this->button9->Name = L"button9";
            this->button9->Size = System::Drawing::Size(31, 25);
            this->button9->TabIndex = 9;
            this->button9->Text = L" ";
            this->button9->UseVisualStyleBackColor = true;
            this->button9->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
            // 
            // button10
            // 
            this->button10->Location = System::Drawing::Point(154, 112);
            this->button10->Name = L"button10";
            this->button10->Size = System::Drawing::Size(31, 25);
            this->button10->TabIndex = 10;
            this->button10->Text = L" ";
            this->button10->UseVisualStyleBackColor = true;
            this->button10->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
        }
    }
Enter fullscreen mode Exit fullscreen mode

The code above should do:

  • Check if what option did the user choose ("Yes" or "No").
  • If the user chose "yes", set match_ended to false.
  • If the user chose "yes", make the "O" go first.
  • If the user chose "yes", reset the winner text to default settings.
  • If the user chose "no", don't do anything, just remove the message box.

  • The code:

            // 
            // button2
            // 
            this->button2->Location = System::Drawing::Point(80, 50);
            this->button2->Name = L"button2";
            this->button2->Size = System::Drawing::Size(31, 25);
            this->button2->TabIndex = 2;
            this->button2->Text = L" ";
            this->button2->UseVisualStyleBackColor = true;
            this->button2->Click += gcnew System::EventHandler(this, &TicTacToe::button_click);
...
Enter fullscreen mode Exit fullscreen mode

will remove all text from all the buttons and reset them to their default settings.

Last but not least, we'll add a "Help" menu strip containing an "About" section.
After the code you added, add the following code:

private: System::Void aboutToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) {
    MessageBox::Show(this,
        "Tic Tac Toe game, v0.1 (initial release)\n"
        "Copyright (C) 2020 David Leal (halfpacho@gmail.com)\n"
        "\nThis project is licensed under GNU General Public License v3.0\n"
        "Visit https://www.gnu.org/licenses/gpl-3.0.en.html for more information about the license.", "About", MessageBoxButtons::OK, MessageBoxIcon::Information);
}
Enter fullscreen mode Exit fullscreen mode

The code above should do:

  • Add a message box saying when was it created, who made it, and the license.

You can find up the full source code at GitHub.
Now, to test your code, compile the source code and now let's test it!

Button to compile the source code

After it just compiled, you'll see something like this:

Hooray! Now you have your Tic Tac Toe game done!
I hope you liked this tutorial. If you found out any bugs, or if the code didn't work for you, please comment and explain your problems.

Share with your friends, if you liked this like it! πŸ˜‰
Follow me on my Twitter and on GitHub.

See you around! πŸ‘‹

Discussion (0)

Forem Open with the Forem app