Search code examples
c++matrixvisual-c++tic-tac-toe

Theoretically big problem with my Tic tac toe game , but for me all seems good


So I went to the next step in learning c++ and that's a matrix. I tried to do an easy tic tac toe game but my game fails to correctly check if the game is over. If you put height = 2 and width = 2 in the first round it says you won... I don't see where could I have messed it up, all seemed pretty good in my mind...

   int map[3][3];
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        map[i][j] = 0;
    }
}

bool finished = false;
int player = 1;
while (!finished) {
    //attack
    cout << "player " << player << " it is your turn"<< endl;

    cout << "The map looks like this:" << endl;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            cout << map[i][j] << " ";
        }
        cout << endl;
    }
    bool correctMove;
    int height, width;
    do
    {
        correctMove = true;
        cout << "Where do you want to attack?" << endl;
        cout << "height = "; cin >> height;
        cout << "width = "; cin >> width;
        if (map[height][width] != 0 || width > 2 || height > 2) {
            correctMove = false;
        }
    } while (!correctMove);
    map[height][width] = player;
    //check finish game
    bool foundSequenceLine = true;
    for (int i = 0; i < 3; i++) {
        if (map[height][i] != player) {
            foundSequenceLine = false;
        }
    }
    bool foundSequenceColumn = true;
    for (int i = 0; i < 3; i++) {
        if (map[i][width] != player) {
            foundSequenceColumn = false;
        }
    }
    bool foundSequenceDiag1 = true;
    if (height == width) {
        for (int i = 0; i < 3; i++) {
            if (map[i][i] != player) {
                foundSequenceDiag1 = false;
            }
        }
    }
    bool foundSequenceDiag2 = true;
    if (height + width == 2) {
        for (int i = 0; i < 3; i++) {
            if (map[2-i][i] != player) {
                foundSequenceDiag2 = false;
            }
        }
    }
    if (foundSequenceColumn || foundSequenceLine || foundSequenceDiag1 || foundSequenceDiag2) {
        finished = true;
        cout << "Congrats player " << player << " you won!!!";
    }

    //change turn
    if (player == 1) {
        player++;
    }
    else {
        player--;
    }
}

}


Solution

  • code makes an assumption, then avoids checking it.

    Your code assumes the player has won unless you can exhaustively prove they haven't.
    The problem is that you then short-circuit two of the tests that prove a move is not a winning move.

    Look at what this code is doing:

       bool foundSequenceDiag1 = true;
        if (height == width) {
            for (int i = 0; i < 3; i++) {
                if (map[i][i] != player) {
                    foundSequenceDiag1 = false;
                }
            }
        }
    

    First, you say "the player has won" foundSequenceDiag1=true;. Then you say, "was the move on a diagonal?", and only then do you run code that can set foundSequenceDiag1 to false.

    If the player makes a move that isn't on the diagonal, the check won't run.

    to fix:

        bool foundSequenceDiag1 = (height==width);  // true if the player played on diagonal
        if (foundSequenceDiag1) {  // loop code now only executes if player played on diagonal
            for (int i = 0; i < 3; i++) {
                if (map[i][i] != player) {
                    foundSequenceDiag1 = false;
                }
            }
        }
    

    when you've found something, stop looking.

    If I were writing your checks, I'd make use of the break keyword to stop looking once I found an answer.

        for (int i = 0; i < 3; i++) {
            if (map[i][i] != player) {
                foundSequenceDiag1 = false;
                break; // can't be true now, so stop checking.
            }
        }