You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言Ncurses主窗口不显示问题修复及子窗口移动求助

问题:Ncurses主窗口无法显示,仅显示子窗口

我是C语言初学者,想要制作一款游戏但遇到了问题。我创建了一个主窗口和一个位于主窗口内的子窗口,希望通过键盘按键移动这个子窗口,因此编写了移动和destroy_win函数。但运行程序时,仅显示子窗口,主窗口无法显示。

原代码:

#include <ncurses.h>
#include <unistd.h>

WINDOW *create_newwin(int height, int width, int y, int x);

void deplacement(int height, int width, int x, int y);

void destroy_win(WINDOW *local_win);

WINDOW* mainwin;
WINDOW* my_win;

int main() {
    // Initialisation de ncurses
    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    curs_set(0);

    // Calcul des positions et tailles des fenêtres
    int height = 30;
    int width = 80;
    int y = (LINES - height) / 2;
    int x = (COLS - width) / 2;

    // Calcul des positions du carré controlé par le Joueur
    int square_height = 2;
    int square_width = 4;
    int square_y = y + (height - square_height) / 2;
    int square_x = x + (width - square_width) / 2;

    // Création de la fenêtre principale
    mainwin = newwin(height, width, y, x);
    box(mainwin, 0 , 0);
    mvwprintw(mainwin, 0, 2, " Score : 0 ");
    mvwprintw(mainwin, 0, 20, " Temps restant : 5.0s ");
    wrefresh(mainwin);

    // Création de la fenêtre du carré    
    my_win = create_newwin(square_height, square_width, square_y, square_x);
    wrefresh(my_win);
    sleep(3);

    
    deplacement(square_height, square_width, square_x, square_y);

    wgetch(my_win);
    // Libération de la mémoire et fermeture de ncurses
    delwin(my_win);
    delwin(mainwin);
    endwin();

    return 0;
}


WINDOW *create_newwin(int height, int width, int y, int x)
{   
    WINDOW *local_win;
    local_win = newwin(height, width, y, x);
    box(local_win, 0 , 0);
    wrefresh(local_win);
    return local_win;
}


void deplacement(int height, int width, int x, int y) {
    int ch = getch();    
    
    while((ch = getch()) != KEY_F(2))
    {
    switch(ch)
    {   
        case KEY_LEFT:              
        destroy_win(my_win);                
        my_win = create_newwin(height, width, y,--x);   
        break;
    
        case KEY_RIGHT:
        destroy_win(my_win);
        my_win = create_newwin(height, width, y,++x);
        break;

        case KEY_UP:
        destroy_win(my_win);
        my_win = create_newwin(height, width, --y,x);
        break;

        case KEY_DOWN:
        destroy_win(my_win);
        my_win = create_newwin(height, width, ++y,x);
        break;  
    }
        wrefresh(my_win);
    }
}


void destroy_win(WINDOW *local_win)
{
    wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' ');

    wrefresh(local_win);
    delwin(local_win);
}

修复方案及修改后代码

核心问题分析:

  1. 主窗口被子窗口覆盖后未重新刷新,导致无法显示
  2. 位置参数采用传值传递,移动操作无法更新实际位置
  3. 输入捕获窗口与keypad设置窗口不匹配

修改后代码:

#include <ncurses.h>
#include <unistd.h>

WINDOW *create_newwin(int height, int width, int y, int x);
void deplacement(int height, int width, int *x, int *y);
void destroy_win(WINDOW *local_win);

WINDOW* mainwin;
WINDOW* my_win;

int main() {
    // Initialisation de ncurses
    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    curs_set(0);

    // Calcul des positions et tailles des fenêtres
    int height = 30;
    int width = 80;
    int y = (LINES - height) / 2;
    int x = (COLS - width) / 2;

    // Calcul des positions du carré controlé par le Joueur
    int square_height = 2;
    int square_width = 4;
    int square_y = y + (height - square_height) / 2;
    int square_x = x + (width - square_width) / 2;

    // Création de la fenêtre principale
    mainwin = newwin(height, width, y, x);
    box(mainwin, 0 , 0);
    mvwprintw(mainwin, 0, 2, " Score : 0 ");
    mvwprintw(mainwin, 0, 20, " Temps restant : 5.0s ");
    wrefresh(mainwin);

    // Création de la fenêtre du carré    
    my_win = create_newwin(square_height, square_width, square_y, square_x);
    // 标记主窗口需要刷新,避免被子窗口覆盖
    touchwin(mainwin);
    wrefresh(mainwin);
    sleep(3);

    // 传递位置指针,确保移动操作能更新实际位置
    deplacement(square_height, square_width, &square_x, &square_y);

    // 从stdscr获取输入,匹配keypad设置
    wgetch(stdscr);
    // Libération de la mémoire et fermeture de ncurses
    delwin(my_win);
    delwin(mainwin);
    endwin();

    return 0;
}

WINDOW *create_newwin(int height, int width, int y, int x)
{   
    WINDOW *local_win;
    local_win = newwin(height, width, y, x);
    box(local_win, 0 , 0);
    wrefresh(local_win);
    return local_win;
}

void deplacement(int height, int width, int *x, int *y) {
    int ch;    
    
    while((ch = getch()) != KEY_F(2))
    {
        switch(ch)
        {   
            case KEY_LEFT:              
                destroy_win(my_win);                
                my_win = create_newwin(height, width, *y, --(*x));   
                break;
        
            case KEY_RIGHT:
                destroy_win(my_win);
                my_win = create_newwin(height, width, *y, ++(*x));
                break;

            case KEY_UP:
                destroy_win(my_win);
                my_win = create_newwin(height, width, --(*y), *x);
                break;

            case KEY_DOWN:
                destroy_win(my_win);
                my_win = create_newwin(height, width, ++(*y), *x);
                break;  
        }
        // 每次移动后刷新主窗口,恢复被覆盖的内容
        touchwin(mainwin);
        wrefresh(mainwin);
        wrefresh(my_win);
    }
}

void destroy_win(WINDOW *local_win)
{
    wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' ');
    wrefresh(local_win);
    delwin(local_win);
}

关键修复点:

  1. 主窗口刷新:在创建子窗口后和每次移动子窗口后,调用touchwin(mainwin)和wrefresh(mainwin),确保主窗口的边框和文字能正确显示。
  2. 位置参数传递:将deplacement函数的位置参数改为指针类型,保证移动操作能更新外部的实际位置变量。
  3. 输入窗口匹配:将wgetch(my_win)改为wgetch(stdscr),与keypad(stdscr, TRUE)的设置保持一致,确保能正确捕获方向键和F2键。

内容的提问来源于stack exchange,提问作者Redwan Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 17:33:17