C语言 尝试删除窗口时出现分段错误

eeq64g8w  于 2022-12-02  发布在  其他
关注(0)|答案(1)|浏览(130)

我只需要WINDOW作为动画的开头和main_menu,但在我通过main_menu中的if语句删除win后,我得到了分段错误,我无法摆脱它。我想删除它,因为当我试图清除它时,边界和“潜行”消失了,但“播放,规则,学分和退出”停留在屏幕上。有什么想法如何删除它正确?

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

void main_menu(int xm, int ym);
void rules(int xm, int ym);

int main(){
    initscr();
    noecho();
    curs_set(0);

    int xm, ym;
    getmaxyx(stdscr, ym, xm);
    WINDOW *win = newwin(ym/2, xm/2, ym/4, xm/4);
    
    box(win, 0, 0);
    mvwprintw(win, ym/4 - 3,  xm/4 - 2, "Play");
    mvwprintw(win, ym/4,  xm/4 - 4, "Options");
    mvwprintw(win, ym/4 + 3,  xm/4 - 2, "Quit");
    wrefresh(win);

    int anim = 2;
    int intro = 3;
    clock_t start_time;
    while(1){
        wclear(win);
        box(win, 0, 0);
        mvwprintw(win, 0, anim, "Snake");

        mvwprintw(win, ym/4, xm/4 - 5, "Loading...");
        wrefresh(win);

        start_time = clock();
        while(clock() < start_time + 30000){}

        if(intro == 3){
            if(anim < xm/2 - 7) anim++;
            else intro--;
        }
        if(intro == 2){
            if(anim > 2) anim--;
            else intro--;
        }
        if(intro == 1){
            if(anim < xm/4 - 2) anim++;
            else intro--;
        }
        if(intro == 0) break;
    }

    wborder(win, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
    wrefresh(win);
    delwin(win);
    main_menu(xm, ym);

    endwin();
    return 0;
}

void main_menu(int xm, int ym){
    WINDOW *win = newwin(ym/2, xm/2, ym/4, xm/4);
    wclear(win);
    box(win, 0, 0);
    
    mvwprintw(win, 0, xm/4 - 2, "Snake");
    wrefresh(win);

    keypad(win, TRUE);
    int selected = 1;
    int slider = 0;

    wattron(win, A_STANDOUT);
    mvwprintw(win, ym/4 - 4,  xm/4 - 2, "Play");
    wattroff(win, A_STANDOUT);
    mvwprintw(win, ym/4 - 1,  xm/4 - 3, "Rules");
    mvwprintw(win, ym/4 + 2,  xm/4 - 3, "Credits");
    mvwprintw(win, ym/4 + 5,  xm/4 - 2, "Quit");
    while(1){
        slider = wgetch(win);
        
        if(slider == KEY_UP){
            if(selected != 1) selected--;
        }

        if(slider == KEY_DOWN){
            if(selected != 4) selected++;
        }

        if(slider == 10){
            wborder(win, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
            wrefresh(win);
            delwin(win);
            if(selected == 2) rules(xm, ym);
        }

        switch(selected){
            case 1:
                wattron(win, A_STANDOUT);
                mvwprintw(win, ym/4 - 4,  xm/4 - 2, "Play");
                wattroff(win, A_STANDOUT);
                mvwprintw(win, ym/4 - 1,  xm/4 - 3, "Rules");
                mvwprintw(win, ym/4 + 2,  xm/4 - 3, "Credits");
                mvwprintw(win, ym/4 + 5,  xm/4 - 2, "Quit");
                break;
            case 2:
                wattron(win, A_STANDOUT);
                mvwprintw(win, ym/4 - 1,  xm/4 - 3, "Rules");
                wattroff(win, A_STANDOUT);
                mvwprintw(win, ym/4 - 4,  xm/4 - 2, "Play");
                mvwprintw(win, ym/4 + 2,  xm/4 - 3, "Credits");
                mvwprintw(win, ym/4 + 5,  xm/4 - 2, "Quit");
                break;
            case 3:
                wattron(win, A_STANDOUT);
                mvwprintw(win, ym/4 + 2,  xm/4 - 3, "Credits");
                wattroff(win, A_STANDOUT);
                mvwprintw(win, ym/4 - 4,  xm/4 - 2, "Play");
                mvwprintw(win, ym/4 - 1,  xm/4 - 3, "Rules");
                mvwprintw(win, ym/4 + 5,  xm/4 - 2, "Quit");
                break;
            case 4:
                wattron(win, A_STANDOUT);
                mvwprintw(win, ym/4 + 5,  xm/4 - 2, "Quit");
                wattroff(win, A_STANDOUT);
                mvwprintw(win, ym/4 - 4,  xm/4 - 2, "Play");
                mvwprintw(win, ym/4 - 1,  xm/4 - 3, "Rules");
                mvwprintw(win, ym/4 + 2,  xm/4 - 3, "Credits");
                break;
            default:
                mvwprintw(win, ym/4 - 4,  xm/4 - 2, "Play");
                mvwprintw(win, ym/4 - 1,  xm/4 - 3, "Rules");
                mvwprintw(win, ym/4 + 2,  xm/4 - 3, "Credits");
                mvwprintw(win, ym/4 + 3,  xm/4 - 2, "Quit");
                break;
        }

        wrefresh(win);
    }
}

void rules(int xm, int ym){
    clear();
    box(win, 0, 0);

    

    //   ─│╲╱
    refresh();
}

我宁愿删除窗口,而不是清除它,因为我只会使用它的main_menu(),也许主要的游戏。

hrysbysz

hrysbysz1#

每当用户按ENTER/RETURN键时,窗口将被删除

if (slider == 10) {
    /* this section looks copy-pasted from `main` */
    wborder(win, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
    wrefresh(win);
    delwin(win); /* <----------- */

    if (selected == 2)
        rules(xm, ym);
}

即使selected2rules也将最终返回到main_menu,并且执行将继续。
在任何情况下,win总是用于switch语句中:

switch (selected) {
    case 1:
        wattron(win, A_STANDOUT);
        /* ... */

这表示您正在dangling pointer上操作。
对于一些简单明了的事情,您可能会发现,如果每个“场景”彼此清楚地分开,那么管理它们会更容易。
下面是一个粗略的重构/概述:

#include <curses.h>
#include <string.h>

enum MENU_OPTIONS { MENU_PLAY, MENU_RULES, MENU_CREDITS, MENU_QUIT, MENU_LENGTH };
static const char *menu_entries[] = { "Play", "Rules", "Credits", "Quit" };

void print_list(WINDOW *w, const char **items, int length, int highlight,
        int y_origin, int x_origin, int spacing)
{
    for (int i = 0; i < length; i++) {
        if (highlight == i)
            wattron(w, A_STANDOUT);

        mvwprintw(w,
            y_origin - (spacing * length / 2) + (i * spacing),
            x_origin - strlen(items[i]) / 2,
            "%s", items[i]);

        if (highlight == i)
            wattroff(w, A_STANDOUT);
    }
}

int main_menu(int xm, int ym, int selected)
{
    WINDOW *win = newwin(ym/2, xm/2, ym/4, xm/4);
    keypad(win, TRUE);

    while (1) {
        werase(win);

        box(win, 0, 0);
        mvwprintw(win, 0, xm/4 - 2, "Snake");

        print_list(win, menu_entries, MENU_LENGTH,
                selected, ym / 4, xm / 4, 2);

        wrefresh(win);

        int input = wgetch(win);

        if (KEY_UP == input || 'w' == input) {
            if (selected != 0) selected--;
        }

        if (KEY_DOWN == input || 's' == input) {
            if (selected != 3) selected++;
        }

        if ('\n' == input || ' ' == input)
            break;
    }

    wclear(win);
    wrefresh(win);
    delwin(win);

    return selected;
}

void fake_loading(int xm, int ym)
{
    WINDOW *win = newwin(ym/2, xm/2, ym/4, xm/4);
    int anim = 2;
    int intro = 3;

    while (1) {
        werase(win);

        box(win, 0, 0);
        mvwprintw(win, 0, anim, "Snake");
        mvwprintw(win, ym/4, xm/4 - 5, "Loading...");

        wrefresh(win);

        napms(30);

        if (intro == 3) {
            if (anim < xm/2 - 7) anim++;
            else intro--;
        }

        if (intro == 2) {
            if(anim > 2) anim--;
            else intro--;
        }

        if (intro == 1) {
            if(anim < xm/4 - 2) anim++;
            else intro--;
        }

        if (intro == 0) break;
    }

    wclear(win);
    wrefresh(win);
    delwin(win);
}

void rules(int xm, int ym)
{
    WINDOW *win = newwin(3, 30, ym / 2 - 1, xm / 2 - 15);

    int wxm, wym;
    getmaxyx(win, wym, wxm);

    box(win, 0, 0);
    mvwprintw(win, 0, wxm / 2 - 6, "Snake - Rules");
    mvwprintw(win, 1, wxm / 2 - 5, "Eat stuff.");

    wrefresh(win);

    wgetch(win);

    wclear(win);
    wrefresh(win);
    delwin(win);
}

int main(void)
{
    initscr();
    noecho();
    curs_set(0);

    int xm, ym;
    getmaxyx(stdscr, ym, xm);

    int running = 1;
    int last_sel = 0;

    fake_loading(xm, ym);

    while (running) {
        erase();

        last_sel = main_menu(xm, ym, last_sel);

        switch (last_sel) {
            case MENU_RULES:
                rules(xm, ym);
                break;
            case MENU_QUIT:
                running = 0;
                break;
        }

        refresh();
    }

    endwin();
}

相关问题