Strange error while adding a feature to my little game (0xC0000005)

0

Hello everyone,

I decided some time ago to write my own version of Minesweepers as some practice and I did it. The game ran perfectly, but after deciding to add a "Choose difficulty" option the window freezes and I get an error message, saying that the program does not respond. Also the line 0xC0000005 appeares. I have tryed many, many things: moving code from main() to a seperate function(now all in int playGame()), allocating some more memory in the heap, even creating a seperate .c file to store some piece of the code, but nothing worked sofar. I came back to the code after a few weeks, but I still have no clue why it is happening. Can anyone help me with this? I hope my code is not hard to read. I added some comments explaining what is what. I am still new to C.

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include "difLvl.c"

    int displayFiled(char **field); //prints out the map of the field
    int combine(char answer, int answer1); //combines user input and field       numeration
    int Randomizer(int **mineArray); //generates random mine map
    int difficulty();
    int playGame();

    int main(){

        int playGame();

        playGame();

        system("PAUSE");

    return 0;
}

int Randomizer(int **mineArray){

    int difficulty();
    int i, j;
    srand(time(NULL));
    int mines;
    int placeMine;
    int totalMines;
    //int difLvl=2;
    int difLvl=difficulty();

    for(i=0, totalMines=0; i<10; i++){
        for(j=0, mines=0; j<10 && mines<difLvl; j++){
            placeMine= rand() % 2;
            mineArray[i][j] = placeMine;
            if(placeMine==1){
                ++mines;
            };
        };
        totalMines+=mines;
    };

    return totalMines;
}

int displayFiled(char **field){

    int i, j;

    printf("    A B C D E F G H I J\n");
    printf("   --------------------\n");
    for (i=0; i<10; i++){
            if (i==9){
                printf("%d |", i+1);
            }else{
                printf("%d  |", i+1);
            };
        for (j=0; j<10; j++){
            printf("%c ", field[i][j]);
            if (j==9){
                printf("\n");
                };
        };
    };
    printf("\n");

    return 0;
}

int playGame(){

    int displayFiled(char **field);
    int combine(char answer, int answer1);
    int Randomizer(int ** mineArray);
    char Y_char; //column as character (a, b, c etc.)
    int X; //row 
    int Y; //Y_char converted to a number 
    int **mineArray; //stores the map of mines
    char **fieldDisplay; //prints out the map of the field
    int i, j; //counters
    int life=1;
    int movePl=0; //no dying on the first move
    int globalMines; //number of mines placed
    int openedFields=0; //counts the number of fields opened
    //int difLvl;
    //int difficulty();

    //difLvl= difficulty();

    /*disabled the trhee lines above while I was trying some solutions*/
    /*int difficulty() is now called from int Randomizer()*/

    system("cls");

    /*Allocates memory to mineArray*/
    mineArray= (int*)calloc(10, sizeof(int));
    for(i = 0; i < 10; i++){
        mineArray[i] = calloc(10, sizeof(int));
    };


    /*Allocates memory to fieldDisplay*/
    fieldDisplay= (int*)calloc(10, sizeof(int));
    for(i = 0; i < 10; i++){
        fieldDisplay[i] = calloc(10, sizeof(int));
    };

    /*default look of fields with ?*/
    for (i=0; i<10; i++){
        for (j=0; j<10; j++){
            fieldDisplay[i][j]='?';
        };
    };

    globalMines= Randomizer(mineArray);

    while(life==1 && openedFields<(100-globalMines)){

        /*for checking purposes only*/
        /*for (i=0; i<10; i++){
            for (j=0; j<10; j++){
                printf("%d ", mineArray[i][j]);
            if (j==9){
                printf("\n");
                };
            };
        };*/

        //printf("\nDifficulty level %d\n", difLvl);
        printf("Total number of mines is %d\n\n", globalMines);
        printf("\tMove nr. %d\n\n", movePl+1);
        displayFiled(fieldDisplay);

        printf("Which field do You want to activate?\nType first the letter, space and then the number (A 1, B 10 etc.)\n");
        scanf("%c %d", &Y_char, &X);
        if (Y_char >= 'A' && Y_char <= 'Z'){
            Y = Y_char - 'A';
        }else if(Y_char >= 'a' && Y_char <= 'z'){
            Y = Y_char - 'a';
        };

        /*checks if a field is a mine*/
        /*X-1 because the player chooses from 1 to 10*/
        if (mineArray[X-1][Y]==0 && fieldDisplay[X-1][Y]=='?'){
            movePl++;
            fieldDisplay[X-1][Y]='0';
            openedFields=openedFields+1;

OPEN :      if (((X-2)<10) && ((X-2)>=0)){
                if (mineArray[X-2][Y]==0 && fieldDisplay[X-2][Y]=='?'){
                    fieldDisplay[X-2][Y]='0';
                    openedFields=openedFields+1;
                };
            };

            if ((X<10) && (X>=0)){
                if (mineArray[X][Y]==0 && fieldDisplay[X][Y]=='?'){
                    fieldDisplay[X][Y]='0';
                    openedFields=openedFields+1;
                };
            };

            if (((Y+1)<10) && ((Y+1)>=0)){
                if (mineArray[X-1][Y+1]==0 && fieldDisplay[X-1][Y+1]=='?'){
                    fieldDisplay[X-1][Y+1]='0';
                    openedFields=openedFields+1;
                };
            };

            if (((Y-1)<10) && ((Y-1)>=0)){
                if (mineArray[X-1][Y-1]==0 && fieldDisplay[X-1][Y-1]=='?'){
                    fieldDisplay[X-1][Y-1]='0';
                    openedFields=openedFields+1;
                };
            };

            system("cls"); //clears console screen
        }else if (mineArray[X-1][Y]==0 && fieldDisplay[X-1][Y]=='0'){
            system("cls");
            printf("You can't choose an already opened field!\n\n");
        }else if(mineArray[X-1][Y]==1 && movePl==0){
        /*only activates on the first turn if players hits mine*/
            movePl++;
            mineArray[X-1][Y]= 0;
            fieldDisplay[X-1][Y]='0';
            globalMines=globalMines-1;
            goto OPEN;
            system("cls");
        }else{
            system("cls");
            printf("YOU DIED ! YOU DIED ! YOU DIED !\n\n");
            printf("Moves successfully made: %d\n\n", movePl-1);
            fieldDisplay[X-1][Y]='1';
            displayFiled(fieldDisplay);
            --life;
        };
    };

    if(openedFields==(100-globalMines)){
        printf("Congratulations! You won the game!\n\n");
        displayFiled(fieldDisplay);
    };

    for(i = 0; i < 10; i++){
        free(mineArray[i]);
    };
    free(mineArray);

    for(i = 0; i < 10; i++){
        free(fieldDisplay[i]);
    };
    free(fieldDisplay);



    return 0;

}

The difLvl.c file:

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

int difficulty(){

    int difLvl;

    while(1){
        printf("Please choose a difficulty level:\n");
        printf("Easy-1\nNormal-2\nNightmare-3\n");
        printf("Your answer: ");
        scanf(" %d", &difLvl);
        if(difLvl>=1 && difLvl<=3){
            break;
        }else{
            system("cls");
            continue;
        };
    };
    system("cls");
    return difLvl;
}

I created it, because I thought that maybe main() had too many code in it and that maybe that was why the difficulty option wasnt working right.

EDIT After the user is promped to enter the difficulty level, the mine map is created, but after choosing a filed, the program crashes.

SOLVED scanf("%c %d", &Y_char, &X); changed to scanf(" %c %d", &Y_char, &X);

c
memory-management
memory-leaks
heap-memory
asked on Stack Overflow May 29, 2015 by Milan Todorovic • edited May 29, 2015 by Milan Todorovic

1 Answer

3

First, you don't allocate your two-dimensional fields correctly. The "outer" field must hold int *, not just int:

mineArray = calloc(10, sizeof(*mineArray));
for (i = 0; i < 10; i++) {
    mineArray[i] = calloc(10, sizeof(*mineArray[i]));
}

Another potential source of the segmentation fault is that Y might end up uninitialised and therefore with a garbage value. The cause is the scanf:

scanf("%c %d", &Y_char, &X);

Most scanf formats skip white space before the conversion, but %c doesn't. It is very likely that you read the newline character as the char for %c when you expect to read a letter. Because the new-line character is white space, you can hot-fix the by placing a space before the %c? format:

scanf(" %c %d", &Y_char, &X);

(I say hot-fix, because it isn't a good solution. scanf doesn't treat new-line characters specially; they are just space. A better solution might be to read a line first with fgets and then scan that with sscanf. At least you can treat each line as frash input. (And your input really should ensure that bad input is ignored.)

Lastly, it is strange that you include a *.c file. If you want to spread ypur project over various files, which is basically a good idea, you should write a header file for each *.c, which has the file's interface. Include the header files in other *.c files; compile the *.c files into objects separately and then link them. This process is usually controlled by Makefiles or Projects.

answered on Stack Overflow May 29, 2015 by M Oehm • edited Mar 28, 2019 by rv7

User contributions licensed under CC BY-SA 3.0