C中的分段错误< curses.h>

wfsdck30  于 2022-12-17  发布在  其他
关注(0)|答案(1)|浏览(182)

我是非常新的编码,所以不要很挑剔,如果我犯了一个简单的错误...我自学成才,所以你是唯一一个我可以问。感谢大家谁会帮助!
我试着用做一些类似“太空射手”的东西<curses.h>,但是它总是给我写分段错误,我不明白为什么。我想我可以给予你我所有的代码,这样你就可以理解游戏的逻辑,但是我想我的问题可能是从诅咒初始化开始到结束...也许我错过了刷新()或类似的东西?

#include <stdio.h>
#include <stdlib.h>
#include<curses.h>
#include<time.h>
#include<string.h>
#include<unistd.h>

int main()
{
    int sizey = 23;
    int sizex = 40;
    int x, y, yi;
    char world[sizey][sizex];
    char player = 'A';
    char playerLaser = '^';
    char enemy = 'M';
    char enemyShielded = 'O';
    char enemyLaser = 'U';
    char explosion = 'X';
    int score = 0;
    int victory = 1;
    int laserReady = 1;
    int enemyReady = 0;

    srand(time(NULL));

    /*welcome screen*/
    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    nodelay(stdscr,TRUE); 
    printf("\n \n     Welcome soldier! \n \n \n \n");
    usleep(1*100000);
    printf("  Brave the COMMAND PROMPT INVADERS and come back a hero. \n \n \n \n");
    usleep(1*10000);
    printf("  Your operating system is depending upon you. \n \n \n \n");
    usleep(1*10000);
    printf("               Good luck.");
    usleep(1*10000);
    printf("\n \n \n \n Press any key to start.");
    getch();
    /*initialise world*/
    int totalEnemies = 0;
    for (x = 0; x < sizex; x ++) {
        for (y = 0; y < sizey; y ++) {
            if ((y+1) % 2 == 0 && y < 7 && x > 4
                && x < sizex - 5 && x % 2 ==0) {
                world[y][x] = enemy;
                totalEnemies ++;
            }
            else if ((y+1) % 2 == 0 && y >= 7 && y < 9 && x > 4
                     && x < sizex - 5 && x % 2 ==0){
                world[y][x] = enemyShielded;
                totalEnemies = totalEnemies + 2;
            }
            else {
                world[y][x] = ' ';
            }
        }
    }
    world[sizey - 1][sizex / 2] = player;
    int i = 1;
    char direction = 'l';
    int currentEnemies = totalEnemies;
    while(currentEnemies > 0 && victory) {
        int drop = 0;
        int enemySpeed = 1 + 10 * currentEnemies / totalEnemies;
        laserReady ++;
        refresh();
        endwin();

        /*display world*/
        system("clear");
        printf("     SCORE:    %d", score);
        printf("\n");
        for (y = 0; y < sizey; y ++) {
            printf("|");
            for (x = 0; x < sizex; x ++) {
                printf("%c",world[y][x]);
            }
            printf("|");
            printf("\n");
        }
        /*laser time*/
        for (x = 0; x < sizex; x ++) {
            for (y = sizey-1; y >= 0; y --) {
                if (i%2 == 0 && world[y][x] == enemyLaser
                    && (world[y+1][x] != enemy & world[y+1][x] != enemyShielded)){
                    world[y+1][x] = enemyLaser;
                    world[y][x] = ' ';
                }
                else if (i%2 == 0 && world[y][x] == enemyLaser
                         && (world[y+1][x] == enemy | world[y+1][x] == enemyShielded)){
                    world[y][x] = ' ';
                }
            }
        }
        for (x = 0; x < sizex; x ++) {
            for (y = 0; y < sizey; y ++) {
                if ((i % 5) == 0 && (world[y][x] == enemyShielded
                                     | world[y][x] == enemy) && (rand() % 15) > 13
                    && world[y+1][x] != playerLaser) {
                    for (yi = y+1; yi < sizey; yi ++) {
                        if (world[yi][x] == enemy
                            | world[yi][x] == enemyShielded) {
                            enemyReady = 0;
                            break;
                        }
                        enemyReady = 1;
                    }
                    if (enemyReady) {
                        world[y+1][x] = enemyLaser;
                    }
                }
                if (world[y][x] == playerLaser && world[y-1][x] == enemy) {
                    world[y][x] = ' ';
                    world[y-1][x] = explosion;
                    currentEnemies --;
                    score = score + 50;
                }
                else if (world[y][x] == playerLaser
                         && world[y-1][x] == enemyShielded) {
                    world[y][x] = ' ';
                    world[y-1][x] = enemy;
                    currentEnemies --;
                    score = score + 50;
                }
                else if (world[y][x] == playerLaser
                         && world[y-1][x] == enemyLaser) {
                    world[y][x] = ' ';
                }
                else if (world[y][x] == explosion) {
                    world[y][x] = ' ';
                }
                else if ((i+1) % 2 == 0 && world[y][x] == enemyLaser
                         && world[y+1][x] == player) {
                    world[y+1][x] = explosion;
                    world[y][x] = ' ';
                    victory = 0;
                }
                else if (world[y][x] == playerLaser
                         && world[y-1][x] != enemyLaser) {
                    world[y][x] = ' ';
                    world[y-1][x] = playerLaser;
                }
            }
        }

        /*update enemy direction*/
        for (y = 0; y < sizey; y ++) {
            if (world[y][0] == enemy) {
                direction = 'r';
                drop = 1;
                break;
            }
            if (world[y][sizex-1] == enemy){
                direction = 'l';
                drop = 1;
                break;
            }
        }

        /*update board*/
        if (i % enemySpeed == 0) {
            if (direction == 'l') {
                for (x = 0; x < sizex - 1; x ++) {
                    for (y = 0; y < sizey; y ++) {
                        if (drop && (world[y-1][x+1] == enemy
                                     || world[y-1][x+1] == enemyShielded)){
                            world[y][x] = world[y-1][x+1];
                            world[y-1][x+1] = ' ';
                        }
                        else if (!drop && (world[y][x+1] == enemy
                                           || world[y][x+1] == enemyShielded)) {
                            world[y][x] = world[y][x+1];
                            world[y][x+1] = ' ';
                        }
                    }
                }
            }
            else {
                for (x = sizex; x > 0; x --) {
                    for (y = 0; y < sizey; y ++) {
                        if (drop && (world[y-1][x-1] == enemy
                                     || world[y-1][x-1] == enemyShielded)) {
                            world[y][x] = world[y-1][x-1];
                            world[y-1][x-1] = ' ';
                        }
                        else if (!drop && (world[y][x-1] == enemy
                                           || world[y][x-1] == enemyShielded)) {
                            world[y][x] = world[y][x-1];
                            world[y][x-1] = ' ';
                        }
                    }
                }
            }
            for (x = 0; x < sizex; x ++) {
                if (world[sizey - 1][x] == enemy) {
                    victory = 0;
                }
            }
        }

/*control player*/
        int ch;
        ch = getch();
        if(ch == 'a'){
            for (x = 0; x < sizex; x = x+1) {
                if ( world[sizey-1][x+1] == player) {
                    world[sizey-1][x] = player;
                    world[sizey-1][x+1] = ' ';
                }
            }
        }

        if(ch == 'd'){
            for (x = sizex - 1; x > 0; x = x-1) {
                if ( world[sizey-1][x-1] == player) {
                    world[sizey-1][x] = player;
                    world[sizey-1][x-1] = ' ';
                }
            }
        }
        if(ch == 'm'&& laserReady > 2){
            for (x = 0; x < sizex; x = x+1) {
                if ( world[sizey-1][x] == player) {
                    world[sizey - 2][x] = playerLaser;
                    laserReady = 0;
                }
            }
        }
        i ++;
        usleep(1*100000);
    }
    system("clear");
    printf("     SCORE:    %d", score);
    printf("\n");
    for (y = 0; y < sizey; y ++) {
        printf("|");
        for (x = 0; x < sizex; x ++) {
            printf("%c",world[y][x]);
        }
        printf("|");
        printf("\n");
    }
    usleep(1*100000);
    system("clear");
    if (victory != 0) {
        printf("\n \n \n \n \n \n               CONGRATULATIONS! \n \n \n \n \n");
        usleep(1*100000);
        printf("\n \n               Score: %d", score);
        usleep(1*100000);
        int bonus = totalEnemies*20 - i;
        printf("\n \n               Bonus: %d", bonus);
        usleep(1*100000);
        printf("\n \n               Total Score: %d", score + bonus);
        printf("\n \n \n \n               Well done");
        usleep(1*100000);
        printf(", Hero.");
        usleep(1*100000);
        getch();
    }
    else {
        printf("\n \n \n \n \n \n               You have failed.");
        usleep(1*100000);
        printf("\n \n \n \n \n \n               Windows is doomed.");
        usleep(1*100000);
        printf("\n \n               Final Score: %d", score);
        getch();
    }
}
pgky5nke

pgky5nke1#

正如上文评论所述:这不是一个诅咒的问题。相反,有许多情况下,你试图访问world[][]数组之外的元素,这就是导致segfault的原因。我没有详细介绍每一个示例,但是,例如,考虑“控制播放器”部分。在“a”(左)处理程序,您可以正确地将单元格的范围从0到(但不包括)sizex...,然后(有时)修改偏移量sizex处的单元格,这超出了范围。
你可以用一种边界安全的方式重写这一节,顺便说一下,这样会更高效:

int playerx = sizex / 2;  /* at main() start -- track the player's
                             position instead of looking through the
                             line to find it each time */
...

/* control player */
int ch;
ch = getch();

if (ch == 'a' && playerx > 0) {
    playerx--;
    world[sizey - 1][playerx] = player;
    world[sizey - 1][playerx + 1] = ' ';
}

if (ch == 'd' && playerx < sizex - 1) {
    playerx++;
    world[sizey - 1][playerx] = player;
    world[sizey - 1][playerx - 1] = ' ';
}

if (ch == 'm' && laserReady > 2) {
    world[sizey - 2][playerx] = playerLaser;
    laserReady = 0;
}

注意,这只是需要检查边界的一个地方。
同时,由于这个 * 是 * 标记的curses...注意整个程序可以很容易地转换为curses:
1.将printf()的所有示例更改为printw()
1.将system(clear)的所有示例更改为erase()
1.将usleep()更改为napms()(除以1000)。
1.将endwin()移到末尾。
1.将nodelay()移到第一个getch()之后。
1.在最后一个erase()之后添加一个nodelay(stdscr, FALSE)
进一步的调整将使它工作得更好。

相关问题