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); }
修复方案及修改后代码
核心问题分析:
- 主窗口被子窗口覆盖后未重新刷新,导致无法显示
- 位置参数采用传值传递,移动操作无法更新实际位置
- 输入捕获窗口与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); }
关键修复点:
- 主窗口刷新:在创建子窗口后和每次移动子窗口后,调用
touchwin(mainwin)和wrefresh(mainwin),确保主窗口的边框和文字能正确显示。 - 位置参数传递:将
deplacement函数的位置参数改为指针类型,保证移动操作能更新外部的实际位置变量。 - 输入窗口匹配:将
wgetch(my_win)改为wgetch(stdscr),与keypad(stdscr, TRUE)的设置保持一致,确保能正确捕获方向键和F2键。
内容的提问来源于stack exchange,提问作者Redwan Khan
相关产品推荐
相关产品推荐

