Search code examples
c++functionint

c++ int in class gets set to value, seemingly out of nowhere


The int winner should be set to 2 under certain conditions but it's somehow being set to a variety of higher values, most commonly 6. I have no idea how this is happening, as there is no other function in my class that affects winner, and the variable isn't even mentioned anywhere else in the program. What is most confusing to me is that I have an almost identical function (P2Move()) that is literally identical in how it sets the winner variable to P1Move(), and that function runs perfectly.

Some info: The class this is part of is called Board, which acts as a checkerboard array made up of Square class objects.

Below is the function causing the problem. Near the bottom, the statement else if((canTake.size()==0)&&(canMove.size()==0)) {Board::winner = 2;} causes the problem. Everything else seems to work when I remove the problematic part from the function, but I need that part to work in order to submit the final project.

void Board::P1Move()
{
    P1pieces = 0;
    std::vector <Move> canMove;
    std::vector <Move> canTake;

    for(int j = 0; j < bSize; j++)
    { //Start of j loop.
        for(int i = 0; i < bSize; i++)
        { //Start of i loop.
            Square sq = board[i][j];
            bool cTakeL = canTakeL(i,j);
            bool cTakeR = canTakeR(i,j);
            bool cMoveL = canMoveL(i,j);
            bool cMoveR = canMoveR(i,j);

            if(board[i][j].getPl() == P1)
            {
                P1pieces++;
                if(cTakeL)
                {
                    Move a = Move(sq.getIndex(),board[i-2][j+2].getIndex(),board[i-1][j+1].getIndex(),0);
                    canTake.push_back(a);
                }
                if(cTakeR)
                {
                    Move b = Move(sq.getIndex(),board[i+2][j+2].getIndex(),board[i+1][j+1].getIndex(),0);
                    canTake.push_back(b);
                }
                if(cMoveL)
                {
                    Move c = Move(sq.getIndex(),board[i-1][j+1].getIndex(),0,0);
                    canMove.push_back(c);
                }
                if(cMoveR)
                {
                    Move d = Move(sq.getIndex(),board[i+1][j+1].getIndex(),0,0);
                    setWinner(d.getSpos());
                    canMove.push_back(d);
                }
            }
        } //End of i loop.
    } //End of j loop.

    if(canTake.size()!=0)
    {
        time_t t;
        time(&t);
        srand(t);
        int moveNum = rand()%canTake.size();
        std::string output = "p1 ";
        Move out = canTake.at(moveNum);
        int i = 0;
        int j = 0;
        for(int y = 0; y < bSize; y++)
        {
            for(int x = 0; x < bSize; x++)
            {
                if(board[x][y].getIndex()==out.getSpos())
                {
                    i = x;
                    j = y;
                }
            }
        }
        if(board[i-2][j+2].getIndex()==out.getEndPos())
        {
            board[i-2][j+2].setOcc(true);
            board[i-2][j+2].setPl(P1);
            board[i-1][j+1].setOcc(false);
            board[i-1][j+1].setPl(NA);
        }
        else if(board[i+2][j+2].getIndex()==out.getEndPos())
        {
            board[i+2][j+2].setOcc(true);
            board[i+2][j+2].setPl(P1);
            board[i+1][j+1].setOcc(false);
            board[i+1][j+1].setPl(NA);
        }
        output = output + out.toString();
        setCmove(output);
        board[i][j].setOcc(false);
        board[i][j].setPl(NA);
    }
    else if(canMove.size()!=0)
    {
        time_t t;
        time(&t);
        srand(t);
        int moveNum = rand()%canMove.size();
        std::string output = "p1 ";
        Move out = canMove.at(moveNum);
        int i = 0;
        int j = 0;
        for(int y = 0; y < bSize; y++)
        {
            for(int x = 0; x < bSize; x++)
            {
                if(board[x][y].getIndex()==out.getSpos())
                {
                    i = x;
                    j = y;
                }
            }
        }
        if(board[i-1][j+1].getIndex()==out.getEndPos())
        {
            board[i-1][j+1].setOcc(true);
            board[i-1][j+1].setPl(P1);
        }
        else if(board[i+1][j+1].getIndex()==out.getEndPos())
        {
            board[i+1][j+1].setOcc(true);
            board[i+1][j+1].setPl(P1);
        }
        output = output + out.toString();
        setCmove(output);
        board[i][j].setOcc(false);
        board[i][j].setPl(NA);
    }
    else if((canTake.size()==0)&&(canMove.size()==0))
    {
        Board::winner = 2;
    }
    P1pieces = canTake.size() + canMove.size();
}


Solution

  • You are working with std::vector, which is a good thing. (Too much beginner "C++" code uses C arrays.) The vector class template allows for a pretty easy way to find out if and where you might have an out-of-bounds access (as suggested in the comments):

    Instead of accessing vector elements using operator[], change your code to use the .at() member function. .at() is bounds-checking, and will throw an exception if you access out-of-bounds (instead of silently breaking your program).

    In production code, operator[] is usually preferred as omitting the bounds check is more efficient. But while learning, .at() can help you quite a bit.

    Also, getting in the habit of using code checkers like valgrind or the assert macro to check your assumptions is a good thing, even when you got past the point where you wouldn't use .at() anymore.