2

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).

Ilya
  • 4,583
  • 4
  • 26
  • 51
kHz-
  • 29
  • 7

2 Answers2

2

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';
Ilya
  • 4,583
  • 4
  • 26
  • 51
  • if I put this condition, at some point it will stop generating Symbols. – kHz- Nov 17 '15 at 10:31
  • I will try the last condition you wrote, TY. But I can't use the operator ? : because my teachers say it's very very bad. – kHz- Nov 17 '15 at 10:33
  • "it will stop generating Symbols"? What are you talking about? Ok, it is not necessary to use ternary operator (but you can see, that my program is two times shorter and simpler). – Ilya Nov 17 '15 at 10:42
  • I mean if i put the condition with logic OR ( || ) it will stop ''generating'' moves at some point, like some boxes will stay ' ' character. But the != ' ' condition is working fine, ty! – kHz- Nov 17 '15 at 10:50
1

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;
}
CiaPan
  • 9,381
  • 2
  • 21
  • 35