Eduardo Barros Eduardo Barros - 1 month ago 4
C Question

Why is this simple C tic-tac-toe program "forgetting" the value at position [0][0] in an array, but works fine for everything else?

The format for inserting a move is xYZ, where x is either 'o' or 'x', Y is the line number and Z is the column number.

If you try to play x11 and then o11, for example, it will correctly point out that it's an invalid play since (1,1) is already occupied. It works for every position BUT (0,0), where for some reason it lets you keep playing the same move over and over.

I also know that it draws the board properly after your move, so if you play o00 it will show a O at (0,0), but then it will forget that position come next turn.

Example: http://image.prntscr.com/image/e002bb6db5da4c7b823bf9bcac7af5eb.png

Code:

#include <stdio.h>

int main() {
int board[3][3] = {0};
int i,j, linha, coluna, valido, run = 1;
char comando[3], jogador, ultimo_jogador;
while(run) {
//recebe o comando para executar esse turno
valido = 0;
do {
printf("Digite a jogada: ");
scanf(" %3[^\n]", comando);
jogador = comando[0];
linha = comando[1]-48;
coluna = comando[2]-48;
if((jogador == 'x' || jogador == 'o') && jogador != ultimo_jogador && board[linha][coluna] == 0) {
if(jogador == 'x') board[linha][coluna] = 1;
else if(jogador == 'o') board[linha][coluna] = 2;
ultimo_jogador = jogador;
valido = 1;
}
else {
printf("Comando inválido\n");
}
} while(!valido);


//desenha o tabuleiro do jogo
for(i=0; i<3; i++) {
for(j=0; j<3; j++) {
if(i == 0 && j == 0) printf("Value at 0,0: %d\n", board[i][j]);
if(board[i][j] == 0) {
printf("_|");
}
else if(board[i][j] == 1) {
printf("X|");
}
else if(board[i][j] == 2) {
printf("O|");
}
}
printf("\n");
}
}
return 0;
}

Answer

You just had a visit of undefined behaviour AKA UB.

I finally found an explanation:

You define comando with a size of 3, but when scanning the string, you're entering 3 chars but you miss the space for the string termination.

In our tests, the value overwrites some local variable like i or j, which is not noticeable since they're initialized afterwards and each time, but your compiler seem to locate the board memory just after the comando buffer (the compiler can do whatever it pleases with local variable addresses)

The result is that you're overwriting the first cell each time you input your value.

Solution: do this:

char comando[4];
Comments