kHz-
kHz-

Reputation: 29

Tic-Tac-Toe without AI

I'm doing homework for UNI and I got to do a Tic-Tac-Toe without any decision taken by player, the moves are all chosen randomly. So if the character on matrix is ' ' it means it's free, while if it's 'X' or 'O' it should generate another move. This is the code (language C):

if (playerTurn == 1){
    playerSymb = 'X';
}
else if (playerTurn == 2){
    playerSymb = 'O';
}

if (matrix[rand1][rand2] == ' '){
    matrix[rand1][rand2] = playerSymb;
} else if(matrix[rand1][rand2] == 'X' || matrix[rand1][rand2] == 'O'){
    do{
        randAlt1 = MINRND + rand()%(MAXRND - MINRND +1);
        randAlt2 = MINRND + rand()%(MAXRND - MINRND +1);
    }while (matrix[randAlt1][randAlt2] != 'X' && matrix[randAlt1][randAlt2] != 'O');
    matrix[randAlt1][randAlt2] = playerSymb;
}

I did not copied the whole code because it's not finished at all, i just need help solving this. But if I try to run this, the Symbols can be overwritten, like if I have a 'X' at matrix[1][2], it's possible that it will be a 'O' after some turns. So how can I make moves do not overwrite? (sorry for bad english).

Upvotes: 2

Views: 495

Answers (2)

CiaPan
CiaPan

Reputation: 9570

You choose an arbitrary position and then test if it is free – possibly multiple times. But you can also choose a number of a free position and then find it.

First set up a turn counter

int   turnNo = 0;

then make a loop for alternate moves, which chooses one of 9-turnNo unused positions, finds it, marks is with a player mark and tests if the move made a line of three:

while(turnNo < 9)
{
    char  currPlayerMark = ...choose 'X' or 'O';

    int   freePos = 9 - turnNo;
    int   currPos = rand() % freePos;  // 0 .. freePos-1

    for(x=0; x<3; x++)
    {
        for(y=0; y<3; y++)
        {
            if(matrix[x][y] == ' ')  // a free position
                if(--currPos < 0)    // the sought one
                    break;           // break the inner loop
        }
        if(currPos < 0)
            break;                   // break the outer loop
    }

    matrix[x][y] = currPlayerMark;

    if(test_for_win_position(x,y))
    {
         message_a_win_of_player(currPlayerMark);
         break;  // turnNo < 9 here
    }

    turnNo ++;
}

Finally test if the loop terminated with no 'win':

if(turnNo == 9)
    message_its_a_draw(); // no-one wins

A function to test the win position might look like this:

int test_for_win_position(int x, int y)
{
    char mark = matrix[x][y];

    // check a column
    if(matrix[x][0] == mark && matrix[x][1] == mark && matrix[x][2] == mark)
        return 1;

    // check a row
    if(matrix[0][y] == mark && matrix[1][y] == mark && matrix[2][y] == mark)
        return 1;

    // check one diagonal
    if(x==y)
        if(matrix[0][0] == mark && matrix[1][1] == mark && matrix[2][2] == mark)
            return 1;

    // check another diagonal
    if(x+y==2)
        if(matrix[0][2] == mark && matrix[1][1] == mark && matrix[2][0] == mark)
            return 1;

    // current player has not won (yet)
    return 0;
}

Upvotes: 1

Ilya
Ilya

Reputation: 4689

Just put correct condition:

while (matrix[randAlt1][randAlt2] == 'X' || matrix[randAlt1][randAlt2] == 'O')

(i.e. try again if this cell is not empty)

Also it is easy to simplify your code without loosing of anything:

randAlt1 = rand1;
randAlt2 = rand2;
while (matrix[randAlt1][randAlt2] != ' ') {
    randAlt1 = MINRND + rand()%(MAXRND - MINRND +1);
    randAlt2 = MINRND + rand()%(MAXRND - MINRND +1);
}
matrix[randAlt1][randAlt2] = (playerTurn == 1) ? 'X' : 'O';

And it is better to add loop guard to prevent infinite loop (or to add special checks for this case):

randAlt1 = rand1;
randAlt2 = rand2;
int nbAttempts = 0;
while (matrix[randAlt1][randAlt2] != ' ' && nbAttempts < 100) {
    randAlt1 = MINRND + rand()%(MAXRND - MINRND +1);
    randAlt2 = MINRND + rand()%(MAXRND - MINRND +1);
    nbAttempts++;
}
if (matrix[randAlt1][randAlt2] != ' ') {
    // show error message and stop the game
}
matrix[randAlt1][randAlt2] = (playerTurn == 1) ? 'X' : 'O';

Upvotes: 2

Related Questions