0

The program is compiling just fine but I keep receiving an output of:

Segmentation fault (code dumped)

The program is designed to play a simple game of tic tac toe with a human and computer that plays a random space. I'm curious as to what this message means and feel it has something to do with my pointers but I'm not sure how or where. Any help is very appreciated. Here's my code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// Initializing board
void clear_table(char board [3][3])
{
int i, j;

//Outer loop for rows
for(i=0; i<3; i++)
{
    //Inner loop for columns
    for(j=0; j<3; j++)
    {
       board[i][j] = ' ';
    }
  }
}

// prints the board in nice format
void display_table (char board [3][3])
{
int i, j;

printf("\n\n The board is: \n");

//Outer loop for rows
for(i=0; i<3; i++)
{
    //Inner loop for columns
    for(j=0; j<3; j++)
    {
        //Printing character
        printf(" %c", board[i][j]);
    }

    printf(" ");

    //Printing footer
    printf("\n _ _ _ \n");
 }
}

//Validates the move
int check_legal_option(char board[3][3], int row, int col)
{
//Checking position
if(board[row][col] == ' ')
{
   //Available
   return 1;
}

return 0;
}

//Function that generates a valid move for player 2
void generate_player2_move(char board[3][3], int *row, int *col)
{
//Validating move
while(1)
{
    //Generating computer position
    *row = rand() % 3;
    *col = rand() % 3;

    //Checking for empty position
    if(check_legal_option(board, *row, *col) == 1)
        break;
  }
}

//Function that checks whether board is full or not
int check_table_full(char board[3][3])
{
int i, j;

//Outer loop for rows
for(i=0; i<3; i++)
{
    //Inner loop for columns
    for(j=0; j<3; j++)
    {
        //Board is not Full
       if(board[i][j] == ' ')
            return 0;
    }
}

//Board Full
return 1;
}

// win returns true if the given player has won on the
// given board, else it returns false
int win (char board [3][3], char player)
{
return (board[0][0] == player && board[0][1] == player && board[0][2] == player) ||
       (board[1][0] == player && board[1][1] == player && board[1][2] == player) ||
       (board[2][0] == player && board[2][1] == player && board[2][2] == player) ||
       (board[0][0] == player && board[1][0] == player && board[2][0] == player) ||
       (board[0][1] == player && board[1][1] == player && board[2][1] == player) ||
       (board[0][2] == player && board[1][2] == player && board[2][2] == player) ||
       (board[0][0] == player && board[1][1] == player && board[2][2] == player) ||
       (board[0][2] == player && board[1][1] == player && board[2][0] == player);

}

//Function that checks for winner
int check_three_in_a_row(char board[3][3], char player1, char player2)
{
//Checking for winning of player
if(win(board, 'X') == 1 && win(board, 'O') == 1)
{
    return 2;
}
//Checking for winning of player 1
else if(win(board, 'O') == 1)
{
    return 0;
}
//Checking for winning of player 2
else if(win(board, 'X') == 1)
{
    return 1;
}
//Tie
else
{
    return -1;
}
}

//Function that plays the game
void playGame(char board[3][3], char player1, char player2)
{
int row, col;
int winner;

//Loop till board is full
while(check_table_full(board) != 1)
{
    //Player turn
    while(1)
    {
        //Reading positions from user
        printf("\n Player 1 enter your selection [row,col]: ");
        scanf("%d %d", &row, &col);

        //Making suitable for array indexing
        row = row - 1;
        col = col - 1;

        //Checking for empty position
        if(check_legal_option(board, row, col) == 1)
           break;
       else
           printf("\n Invalid choice... Try again!! \n ");
    }

    //Storing in array
    board[row][col] = player1;

    //Printing board
    display_table(board);

    //Finding winner
    winner = check_three_in_a_row(board, player1, player2);

    //If either of winner is found
    if(winner >= 0 && winner <= 2)
    {
        //Printing winner
        switch(winner)
        {
            //Displaying winner
            case 0: printf("\n Player 1 won the game... \n"); break;
            case 1: printf("\n Player 2 won the game... \n"); break;
            case 2: printf("\n Game Tie ... \n"); break;
        }

        return;
    }

    //Generating a move
    generate_player2_move(board, &row, &col);

    //Storing in array
    board[row][col] = player2;

    printf("\n Player 2 has entered [row,col]: %d,%d \n", row+1, col+1);

    //Printing board
    display_table(board);

    //Finding winner
    winner = check_three_in_a_row(board, player1, player2);

    //If either of winner is found
    if(winner >= 0 && winner <= 2)
    {
        //Printing winner
        switch(winner)
        {
            //Displaying winner
            case 0: printf("\n Player 1 won the game... \n"); break;
            case 1: printf("\n Player 2 won the game... \n"); break;
            case 2: printf("\n Game Tie ... \n"); break;
        }

        return;
    }
  }
}

//Main function
int main()
{
//Board
char board[3][3];

//Player characters
char player1Character='O', player2Character='X';

//Initializing random function
srand(time(NULL));

//Initializing board
clear_table(board);

//Printing board
display_table(board);

//Playing game
playGame(board, player1Character, player2Character);

return 0;
}
student
  • 5
  • 1
  • Run your code through [valgrind](http://valgrind.org). – dbush Nov 27 '17 at 21:21
  • Please debug to identify the line which causes the segfault. Helpful reads: https://ericlippert.com/2014/03/05/how-to-debug-small-programs/ https://stackoverflow.com/questions/2069367/how-to-debug-using-gdb Or add lots of printfs() to keep track of what happens. – Yunnosch Nov 27 '17 at 21:24
  • you sure you're entering 1-3 for `row` and `col`? – yano Nov 27 '17 at 21:26
  • It looks fine to me as long as the entered numbers are in range. in `check_legal_option`, you should first check that the values of `row` and `col` range from 0 to 2. – dbush Nov 27 '17 at 21:26
  • Check the result of `scanf("%d %d", &row, &col);`, if this fails, you have a high risk of accessing outside the array. Initialising row and col to a harmless value might avoid the segfault for starters ... Maybe double check validity of row and col inside `check_legal_option()` before accesssing the array with them as indexes. – Yunnosch Nov 27 '17 at 21:31

1 Answers1

0

The problem is right here, at the start of the PlayGame function:

//Reading positions from user
printf("\n Player 1 enter your selection [row,col]: ");
scanf("%d %d", &row, &col);

The prompt seems to suggest that you should enter two numbers separated by a comma, like 2,2 to get the center position.

However, the format string scanf("%d %d" doesn't say anything about a comma, so the input fails and col never gets a value.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203