向我的小游戏添加功能时出现奇怪错误 (0xC0000005)

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

大家好,

前段时间我决定编写自己的扫雷版本作为练习,我做到了。游戏 运行 完美,但在决定添加“选择难度”选项后 window 冻结,我收到一条错误消息,说程序没有响应。 0xC0000005 行也出现了。我已经尝试了很多很多事情:将代码从 main() 移动到一个单独的函数(现在全部在 int playGame() 中),分配一些堆中的更多内存,甚至创建一个单独的 .c 文件来存储一些代码,但到目前为止没有任何效果。几周后我回到了代码,但我仍然不知道为什么会这样。 谁能帮我这个?我希望我的代码不难读。我添加了一些评论来解释什么是什么。我还是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;

}

difLvl.c 文件:

#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;
}

我创建了它,因为我认为也许 main() 中的代码太多,这也许就是难度选项无法正常工作的原因。

编辑 提示用户输入难度级别后,创建了矿山地图,但选择了一个文件后,程序崩溃了。

已解决 scanf("%c %d", &Y_char, &X); 变成 scanf(" %c %d", &Y_char, &X);

首先,你没有正确分配你的二维字段。 "outer" 字段必须包含 int *,而不仅仅是 int:

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

分段错误的另一个潜在来源是 Y 可能最终未初始化,因此具有垃圾值。原因是 scanf:

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

大多数 scanf 格式在转换前跳过白色 space,但 %c 不会。当您希望阅读一个字母时,很可能您将换行符读作 %c 的字符。因为换行符是白色的 space,你可以通过在 %c 之前放置一个 space 来修复它?格式:

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

(我说热修复,因为它不是一个好的解决方案。scanf 不特别对待换行符;它们只是 space。更好的解决方案可能是首先用 fgets 读取一行,然后用 sscanf 扫描它。至少你可以把每一行都当作 frash 输入。(你的输入确实应该确保忽略错误的输入。)

最后,奇怪的是你包含了一个*.c文件。如果你想将 ypur 项目分布在各种文件上,这基本上是个好主意,你应该为每个 *.c 编写一个头文件,它有文件的接口。在其他 *.c 个文件中包含头文件;分别将 *.c 个文件编译成对象,然后 link 它们。这个过程通常由 Makefiles 或 Projects 控制。