0

I made a 10x10 tic-tac-toe program and the winner is the player who has 5 marked in a row,column and diagonals. When I put 'X' or 'O' in the first column, which is 0, or the last column, which is 9, for example: 8 0, 9 0, 0 9. There will be a second mark on the other column which are 8 0->7 9, 9 0->8 9, 0 9->1 0.

   0   1   2   3   4   5   6   7   8   9
 |---|---|---|---|---|---|---|---|---|---|
0|   |   |   |   |   |   |   |   |   | X |
 |---|---|---|---|---|---|---|---|---|---|
1| X |   |   |   |   |   |   |   |   |   |
 |---|---|---|---|---|---|---|---|---|---|
2|   |   |   |   |   |   |   |   |   |   |
 |---|---|---|---|---|---|---|---|---|---|
3|   |   |   |   |   |   |   |   |   |   |
 |---|---|---|---|---|---|---|---|---|---|
4|   |   |   |   |   |   |   |   |   |   |
 |---|---|---|---|---|---|---|---|---|---|
5|   |   |   |   |   |   |   |   |   |   |
 |---|---|---|---|---|---|---|---|---|---|
6|   |   |   |   |   |   |   |   |   |   |
 |---|---|---|---|---|---|---|---|---|---|
7|   |   |   |   |   |   |   |   |   | X |
 |---|---|---|---|---|---|---|---|---|---|
8| X |   |   |   |   |   |   |   |   | O |
 |---|---|---|---|---|---|---|---|---|---|
9| O |   |   |   |   |   |   |   |   |   |
 |---|---|---|---|---|---|---|---|---|---|

Here is the code:

#include <stdio.h>
#include <time.h>
char board[9][9];
const char PLAYER ='X';
const char PLAYER2 = 'O';
const char BOT ='O';

void resetBoard(){
    int i,j;
    for(i=0;i<10;i++){
        for(j=0;j<10;j++){
            board[i][j]=' ';
        }
    }
}

printBoard(){
    printf("   0   1   2   3   4   5   6   7   8   9");
    printf("\n |---|---|---|---|---|---|---|---|---|---|");
    printf("\n0| %c | %c | %c | %c | %c | %c | %c | %c | %c | %c |",board[0][0],board[0][1],board[0][2],board[0][3],board[0][4],board[0][5],board[0][6],board[0][7],board[0][8],board[0][9]);
    printf("\n |---|---|---|---|---|---|---|---|---|---|");
    printf("\n1| %c | %c | %c | %c | %c | %c | %c | %c | %c | %c |",board[1][0],board[1][1],board[1][2],board[1][3],board[1][4],board[1][5],board[1][6],board[1][7],board[1][8],board[1][9]);
    printf("\n |---|---|---|---|---|---|---|---|---|---|");
    printf("\n2| %c | %c | %c | %c | %c | %c | %c | %c | %c | %c |",board[2][0],board[2][1],board[2][2],board[2][3],board[2][4],board[2][5],board[2][6],board[2][7],board[2][8],board[2][9]);
    printf("\n |---|---|---|---|---|---|---|---|---|---|");
    printf("\n3| %c | %c | %c | %c | %c | %c | %c | %c | %c | %c |",board[3][0],board[3][1],board[3][2],board[3][3],board[3][4],board[3][5],board[3][6],board[3][7],board[3][8],board[3][9]);
    printf("\n |---|---|---|---|---|---|---|---|---|---|");
    printf("\n4| %c | %c | %c | %c | %c | %c | %c | %c | %c | %c |",board[4][0],board[4][1],board[4][2],board[4][3],board[4][4],board[4][5],board[4][6],board[4][7],board[4][8],board[4][9]);
    printf("\n |---|---|---|---|---|---|---|---|---|---|");
    printf("\n5| %c | %c | %c | %c | %c | %c | %c | %c | %c | %c |",board[5][0],board[5][1],board[5][2],board[5][3],board[5][4],board[5][5],board[5][6],board[5][7],board[5][8],board[5][9]);
    printf("\n |---|---|---|---|---|---|---|---|---|---|");
    printf("\n6| %c | %c | %c | %c | %c | %c | %c | %c | %c | %c |",board[6][0],board[6][1],board[6][2],board[6][3],board[6][4],board[6][5],board[6][6],board[6][7],board[6][8],board[6][9]);
    printf("\n |---|---|---|---|---|---|---|---|---|---|");
    printf("\n7| %c | %c | %c | %c | %c | %c | %c | %c | %c | %c |",board[7][0],board[7][1],board[7][2],board[7][3],board[7][4],board[7][5],board[7][6],board[7][7],board[7][8],board[7][9]);
    printf("\n |---|---|---|---|---|---|---|---|---|---|");
    printf("\n8| %c | %c | %c | %c | %c | %c | %c | %c | %c | %c |",board[8][0],board[8][1],board[8][2],board[8][3],board[8][4],board[8][5],board[8][6],board[8][7],board[8][8],board[8][9]);
    printf("\n |---|---|---|---|---|---|---|---|---|---|");
    printf("\n9| %c | %c | %c | %c | %c | %c | %c | %c | %c | %c |",board[9][0],board[9][1],board[9][2],board[9][3],board[9][4],board[9][5],board[9][6],board[9][7],board[9][8],board[9][9]);
    printf("\n |---|---|---|---|---|---|---|---|---|---|");
}

void printWinner(char winner){
    if (winner==PLAYER){
        printf("\nYou win!");
    }
    else if(winner==BOT){
        printf("\nYou lose!");
    }
    else printf("\nTie!");
}

void printWinnerHuman(char winner){
    if (winner==PLAYER){
        printf("\nPlayer 1 wins!");
    }
    else if(winner==PLAYER2){
        printf("\nPlayer 2 wins!");
    }
    else printf("\nTie!");
}

void playerMove(){
    int x,y;
    do{
        printf("\nYou are X!");
        printf("\nEnter move (Ex: 0 2): ");
        scanf("%d %d",&x,&y);
        if (board[x][y]!=' '){
            printf("\n\n\n\n\n\n\nSpace already taken\n");
            printf("\nTry another move!\n");
            printBoard();
        }
        else {
            board[x][y]=PLAYER;
            break;
        }
    }
    while(board[x][y]!=' ');
}

void player2Move(){
    int x,y;
    do{
        printf("\n\nYou are O!");
        printf("\nEnter your move (Ex: 1 2): ");
        scanf("%d %d",&x,&y);
        if(board[x][y]!=' '){
            printf("\nSpace already taken!\n");
            printBoard();
        }
        else{
            board[x][y]=PLAYER2;
            break;
        }
    }
    while(board[x][y]!=' ');
}

void botMove(){
    //create random moves for bot
    srand(time(0));
    int x,y;
    if(checkFreeSpaces()>0){
        do{
            x=rand()%9;
            y=rand()%9;
        }
        while(board[x][y]!=' ');
        board[x][y]=BOT;
    }
    else printWinner(' ');
}

char checkWinner(){
    int i,j;
    int found=0;
    int count=0;
    //check rows winner
    for(i=0;i<10;i++){
        if(count<4){
            count=0;
            for(j=0;j<10;j++){
                if (board[i][j]==board[i][j+1]&&board[i][j]!=' '){
                    count++;
                    if(count==4){
                    return board[i][j];
                    }
                }
            }   
        }
    }
    //check columns winner
    for(i=0;i<10;i++){
        if(count<4){
            count=0;
            for(j=0;j<10;j++){
                if (board[j][i]==board[j+1][i]&&board[j][i]!=' '){
                    count++;
                    if(count==4){
                        return board[j][i];
                    }
                }
            }
        }
    }
    //check all diagonals above MAIN diagonals(\*)
    int row;
    int column;
    for(i=5;i>=0;i--){
        column=i;
        row=0;
        count=0;
        for(j=0;j<10;j++){
            if(board[row][column]==board[row+1][column+1]&&board[row][column]!=' '){
                row++;
                column++;
                count++;
                if(count==4){
                    return board[row][column];
                }
                else if(board[row][column]==board[row+1][column+1]&&board[row][column]==' '){
                row++;
                column++;
                }
            }
        }       
    }
    //check all diagonals above SECOND diagonal(*/)
    for(i=4;i<10;i++){
        column=i;
        row=0;
        count=0;
        for(j=0;j<10;j++){
            if(board[row][column]==board[row+1][column-1]&&board[row][column]!=' '){
                row++;
                column--;
                count++;
                if(count==4){
                    return board[row][column];
                }
            else if(board[row][column]==board[row+1][column-1]&&board[row][column]==' '){
                row++;
                column--;   
            }
            }
        }   
    }
    //check all diagonals below MAIN diagonal(*\)
    for(i=1;i<10;i++){
        row=i;
        column=0;
        count=0;
        for(j=0;j<10;j++){
            if(board[row][column]==board[row+1][column+1]&&board[row][column]!=' '){
                row++;
                column++;
                count++;
                if(count==4){
                    return board[row][column];
                }
                else if(board[row][column]==board[row+1][column+1]&&board[row][column]==' '){
                    row++;
                    column++;
                }
            }
        }
    }
    //check all diagonals below SECOND diagonal(\*)
    for(i=1;i<10;i++){
        row=i;
        column=9;
        count=0;
        for(j=0;j<10;j++){
            if(board[row][column]==board[row+1][column-1]&&board[row][column]!=' '){
                row++;
                column--;
                count++;
                if(count==4){
                    return board[row][column];
                }
                else if(board[row][column]==board[row+1][column-1]&&board[row][column]==' '){
                    row++;
                    column--;
                }
            }
        }
    }
        return ' '; //no winners
    }
    
int checkFreeSpaces(){
    int i,j;
    int freeSpaces=100;
    for(i=0;i<10;++i){
        for(j=0;j<10;++j){
            if (board[i][j]!=' '){
                freeSpaces--;
            }
        }
    }
    return freeSpaces;
}

void humanPlay(){
    resetBoard(); //reset default declaration of computer
        char winner =' ';
        while(winner == ' ' &&checkFreeSpaces()!=0){     //while there is no winner and there are still spaces
            printBoard();
            playerMove();
            winner=checkWinner();   //after every move of player, program checks if there is a winner and if there are spaces left.
            if(winner!=' ' || checkFreeSpaces()==0){
                break;
            }
            printBoard();
            player2Move();
            winner=checkWinner();
            if(winner!=' '||checkFreeSpaces()==0){          //if there is no spaces left and no winner, break loop.
                break;
            }
        }
        printBoard();
        printWinnerHuman(winner);
        
    }

    
void botPlay(){
    resetBoard(); //reset default declarartion of computer
        char winner =' ';
        while(winner == ' ' &&checkFreeSpaces()!=0){    //while there is no winner and there are still spaces
            printBoard();
            playerMove();
            winner=checkWinner();   //after every move of player, program checks if there is a winner and if there are spaces left.
            if(winner!=' ' || checkFreeSpaces()==0){
                break;
            }
            botMove();
            winner=checkWinner();
            if(winner!=' ' || checkFreeSpaces()==0){
                break;
            }
        }
        printBoard();
        printWinner(winner);
    }


//main
int main(){
    humanPlay();
    return 0;
}

I tried looking again at the printBoard() function to check if i misstyped any matrix position but i didn't see any

  • 3
    According to the picture the array board shall be declared like char board[10][10]; instead of char board[9][9]; – Vlad from Moscow Mar 13 '23 at 11:11
  • 2
    Side note: your usage of `srand(time(0));` looks weird. [c - srand() — why call it only once? - Stack Overflow](https://stackoverflow.com/questions/7343833/srand-why-call-it-only-once) – MikeCAT Mar 13 '23 at 11:11
  • 1
    @MikeCAT if I understand you correctly, you meant that I should only call srand() fuction once, instead of calling it everytime the function botMove() is called, right? – SongPhuc1910 Mar 13 '23 at 11:17
  • 1
    @SongPhuc1910 Yes, I meant so. – MikeCAT Mar 13 '23 at 11:18
  • Side note: Your function `printBoard` can be made much simpler by using nested loops. I have rewritten that function for you. [Here](https://godbolt.org/z/d5Mbox6PG) is a demonstration of it. – Andreas Wenzel Mar 13 '23 at 14:22

2 Answers2

3

You have to specify not the maximum index but the number of elements when you declare arrays in C.

The available indice for the array char board[9][9]; is 0 to 8 for each dimension.

Allocate enough elements like char board[10][10]; to fix the error.

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
1

If you want ten elements in both X and Y dimensions, you need to declare ten elements in each dimension! You have char board[9][9], not char board[10][10]. The maximum legitimate index in either X or Y is therefore 8 (range 0...8, giving nine discrete possibilities). The total number of declared elements is 81 (9*9).

You're sleepwalking into disaster, through array overrun. You've declared a total of 81 (9*9) elements, but you're indexing up to the 100th element, at board[9][9]. Once you write past the 81st element, you're corrupting someone else's memory.

I'd add that your board display function is ugly. Consider how you could do it with two nested loops instead.

You could also replace the contents of your resetBoard() function with a simple memset(board, ' ', sizeof(board));.

One more thing: you don't range-check the co-ordinates your human player enters. That's a whole new set of possibilities for under/overrun!

Remember the old joke: "A software tester walks into a pub. Orders a beer. Orders zero beers. Orders a googolplex beers. Orders the square root of -23 beers. Orders a woolly mammoth." Always check your inputs!

Jon Green
  • 345
  • 2
  • 5