Search code examples
c++multidimensional-arraywhile-loopgoto

When using the goto statement code does not output at wanted inside of a loop


I am trying to make a simple tic-tac-toe game. Right now I am trying to make it so the computer can't place inside of certain places in a 2d array. The computer is set to place randomly, and I am using loops and goto to make it random until it gets a suitable spot.

#include <iostream>
#include <string>
#include <ctime>
#include <Windows.h>

using namespace std;

string team;
string a = "  ";
const int rows = 5;
const int elements = 5;

string Board[rows][elements] = { a, "| ", a, "| ", a,
    "- ", "+ ", "- ", "+ ", "- ",
    a, "| ", a, "| ", a,
    "- ", "+ ", "- ", "+ ", "- ",
    a, "| ", a, "| ", a };

void showBoard()
{
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < elements; j++) {
            cout << Board[i][j];
        }
        cout << endl;
    }
}

int main()
{
    int nonFilled = 0;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < elements; j++) {
            if (Board[i][j] == a && a == "  ")
                nonFilled++;
        }
    }

    int circleFilled = 0;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < elements; j++) {
            if (Board[i][j] == a && a == "0 ")
                circleFilled++;
        }
    }
    int crossFilled = 0;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < elements; j++) {
            if (Board[i][j] == a && a == "X ")
                crossFilled++;
        }
    }

    cout << "Welcome to tic-tac-toe game." << endl;
    cout << endl;

    showBoard();

    cout << "Please select team if circle or cross: (0/X)" << endl;
    cin >> team;

    if (team == "0") {
        int ifCircle = 1;
        cout << "You have selected circle." << endl;
        while (nonFilled > circleFilled + crossFilled) {
            srand(time(NULL));
            int x, y = 0;
            int xx, xy = 0;
            cout << "Select square: " << endl;
            cout << "Y cord (0-4): ";
            cin >> x;
            cout << endl;
            cout << "X cord (0-4): ";
            cin >> y;
            if (x == 0 || y == 0)
                return 0;

            /*if (Board[x - 1][y - 1] = "| ", "+ ", "- ")
            {
                cout << "You cannot place one there. " << endl;
                nonFilled = 100;
            }*/

            int b = 1;
            if (Board[x - 1][y - 1] == a)
                b = 1;
            else
                b = 2;

            switch (b) {
            case 1:
                Board[x - 1][y - 1] = "0 ";
                break;

            case 2:
                cout << "You cannot place one there. " << endl;
                continue;
            }

            /* if (Board[x - 1][y - 1] == a)
            {
                Board[x - 1][y - 1] = "0 ";
            }
            else
            {
                cout << "You cannot place one there." << endl;
                
            }*/

            cout << endl;

            showBoard();
            cout << "The opponent will now pick a square:" << endl;
            system("pause");

            xx = rand() % rows;
            xy = rand() % elements;

            int c = 1;
            if (Board[xx][xy] == a)
                c = 1;
            else if (Board[xx][xy] == "| ", "+ ", "- ")
                c = 2;

            switch (c) {

            case 1:
                Board[xx][xy] = "X ";
                break;

            case 2: {

            LOOP: // here is my label for the goto statement

                while (true) // this loop
                {

                    xx = rand() % rows;
                    xy = rand() % elements;

                    if (Board[xx][xy] == "| ", "+ ", "- ") {
                        goto LOOP; // goto statement
                    }
                    else {
                        Board[xx][xy] = "X ";
                    }
                }
            }
            }

            cout << endl;

            cout << "The opponent has picked:" << endl;
            showBoard();
        }
    }

    else if (team == "X") {
        int ifCircle = 0;
    }
    system("pause");
    return 0;
}

The loop in question is at the very bottom, I am not sure if it is a problem with how I placed the label or how I am using the statement or if it is a problem with a different part of the code.

I have looked at loads of questions on goto statements inside of while loops and I couldn't find anything.


Solution

  • The immediate problem lies neither with the placement of your LOOP: label nor with the use of the goto statement (and I am not here going to get involved in the argument over whether or not that keyword should ever be used in a C++ program).

    The problem is in the following line:

    if (Board[xx][xy] == "| ", "+ ", "- ") {
    

    (and the similar if else... statement a few lines earlier).

    This does not do what you may want it to! In fact, it will always return a true value, as the nett result of the expression is simply, if ("- ") - which will always be a non-null (i.e. non-zero) address of the string literal.

    What you need (if you are looking to match the indexed Board[][] string to any one of the three literals) is the following:

    if (Board[xx][xy] == "| " || Board[xx][xy] == "+ " || Board[xx][xy] == "- ") {
        //...
    

    The code you have, using the comma operator, evaluates each of the comma-separated expressions (in left-to-right order), discarding each but the last (right-most) value; the overall result is just that of the right-most expression.


    EDIT: Having applied the fixes I suggested above, I then noticed another problem: Your while loop, as it stands, will never exit (either it will goto to the LOOP: or just keep running). Here is one (quick) way to fix the loop, which also removes the need for the goto statement:

                case 2:
                {
                    bool done = false;
                    while (!done)
                    {
                        xx = rand() % rows;
                        xy = rand() % elements;
    
                        if (Board[xx][xy] == "| " || Board[xx][xy] == "+ " || Board[xx][xy] == "- ") {
                            continue;
                        }
                        else {
                            Board[xx][xy] = "X ";
                            done = true;
                        }
                    }
                }
    

    There are more 'elegant' ways to achieve the same result but, hopefully, you will at least be able to follow (and understand) the fairly minor changes I have made to your code. Please feel free to ask for any further clarification and/or explanation.