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

ncurses颜色无法生效求助:attron/wattron等函数均无效

解决NCurses中颜色设置无效的问题

你遇到的核心问题是你在操作自定义窗口win,但却用了针对全局stdscr的attron()/attroff()函数——这些属性设置不会自动应用到你创建的newwin()窗口上,必须使用窗口专属的属性操作函数。

问题根源拆解

  • attron(COLOR_PAIR(1))只会修改全局窗口stdscr的属性,而你实际在自定义窗口win上调用mvwaddch(),所以颜色根本没生效;
  • 原代码仅在清除第二个对象时设置了颜色属性,但绘制字符时属性已经被取消,等于白设置;
  • 缺少终端颜色支持的前置检查,万一终端不支持颜色,也无法提前知晓问题。

修改后的完整代码

#include "stdio.h"
#include "ncurses.h"
#include "math.h"
#include "unistd.h"
#include "stdlib.h"
#include <stdbool.h> // 补全bool类型所需头文件

double PI = 3.15927;
bool drawObject(WINDOW *win, int **obj, int size, int y, int x);
bool clearObject(WINDOW *win, int **obj, int size, int y, int x);
bool drawPoint(WINDOW *win, int y, int x, char c);

bool drawPoint(WINDOW *win, int y, int x, char c) {
 bool r = mvwinch(win, y, x) != 0x20;
 mvwaddch(win, y, x, c);
 return r;
}

bool drawObject(WINDOW *win, int **obj, int size, int y, int x) {
 int k;
 bool r = false;
 for (k = 0; k < size; ++k) {
 r |= drawPoint(win, y + obj[k][0], x + obj[k][1], (char)obj[k][2]);
 }
 wrefresh(win);
 return r;
}

bool clearObject(WINDOW *win, int **obj, int size, int y, int x) {
 int k;
 for (k = 0; k < size; ++k) {
 mvwaddch(win, y + obj[k][0], x + obj[k][1], ' ');
 }
 wrefresh(win);
 return true; // 补全函数声明要求的返回值
}

int main(int argc, char **argv) {
 int k = 0;
 WINDOW *win, *status;
 int ox = 40, oy = 20;
 bool isCrash = false;
 int obj1_size = 6;
 int **obj1_def = (int**)malloc(sizeof(int*) * obj1_size);
 for (k = 0; k < obj1_size; ++k) {
 obj1_def[k] = (int*)malloc(sizeof(int) * 3);
 }
 obj1_def[0][0] = 0;
 obj1_def[0][1] = 1;
 obj1_def[0][2] = (int)'\\';
 obj1_def[1][0] = 0;
 obj1_def[1][1] = -1;
 obj1_def[1][2] = (int)'/';
 obj1_def[2][0] = 1;
 obj1_def[2][1] = 0;
 obj1_def[2][2] = (int)'W';
 obj1_def[3][0] = 0;
 obj1_def[3][1] = 0;
 obj1_def[3][2] = (int)'H';
 obj1_def[4][0] = -1;
 obj1_def[4][1] = 0;
 obj1_def[4][2] = (int)'H';
 obj1_def[5][0] = -2;
 obj1_def[5][1] = 0;
 obj1_def[5][2] = (int)'A';
 double obj1_step = PI / 50;
 double obj1_t = 1.5;
 int obj1_a = 4;
 int obj1_x = 0, obj1_y = 0;
 double obj2_step = PI / 20;
 double obj2_t = 0;
 int obj2_a = 3;
 int obj2_b = 10;
 int obj2_x = 0, obj2_y = 0;

 initscr();
 refresh();

 // 新增:检查终端是否支持颜色
 if (!has_colors()) {
     endwin();
     fprintf(stderr, "终端不支持颜色!\n");
     return 1;
 }
 if (!can_change_color()) {
     fprintf(stderr, "终端不允许修改颜色!\n");
 }

 startcolor();
 init_pair(1, COLOR_RED, COLOR_BLACK); // 定义颜色对:前景红,背景黑

 win = newwin(40, 80, 0, 0);
 status = newwin(2, 80, 40, 0);
 wrefresh(win);
 wrefresh(status);

 while (true) {
 // 第一个对象
 clearObject(win, obj1_def, obj1_size, obj1_y, obj1_x);
 obj1_x =(int)(3 * obj1_t * sin(obj1_t * 0.5) * cos(obj1_t));
 obj1_y =(int)(2 * obj1_t * cos(obj1_t * 1.5) * cos(obj1_t));
 obj1_x += 50;
 obj1_y += 20;
 if (obj1_x < 1) {
 obj1_x = 1;
 }
 if (obj1_x > 78) {
 obj1_x = 78;
 }
 if (obj1_y < 2) {
 obj1_y = 2;
 }
 if (obj1_y > 38) {
 obj1_y = 38;
 }
 isCrash = drawObject(win, obj1_def, obj1_size, obj1_y, obj1_x);
 if (isCrash == true) {
 mvwprintw(status, 0, 0, "[%d, %d] [%d, %d]", obj1_x, obj1_y, obj2_x, obj2_y);
 mvwprintw(status, 1, 0, "Crash !!!");
 break;
 }
 obj1_t += obj1_step;
 if (obj1_t > 17.215) {
 obj1_t = 1.5;
 }
 // 第二个对象
 // 关键修改:用窗口专属的wattron/wattroff设置颜色属性
 wattron(win, COLOR_PAIR(1));
 // 清除旧位置
 mvwaddch(win, obj2_y, obj2_x, ' ');
 mvwaddch(win, obj2_y, obj2_x+1, ' ');
 mvwaddch(win, obj2_y, obj2_x-1, ' ');
 mvwaddch(win, obj2_y-1, obj2_x, ' ');
 mvwaddch(win, obj2_y-1, obj2_x-1, ' ');
 // 绘制新位置(在属性生效范围内)
 mvwaddch(win, obj2_y, obj2_x+1, '-');
 mvwaddch(win, obj2_y, obj2_x-1, '-');
 mvwaddch(win, obj2_y, obj2_x, '-');
 mvwaddch(win, obj2_y-1, obj2_x, '\\');
 mvwaddch(win, obj2_y-1, obj2_x-1, '\\');
 wattroff(win, COLOR_PAIR(1));
 wrefresh(win);

 // 修复笔误:原代码误用obj1_t计算第二个对象位置,改为obj2_t
 obj2_x =(int)(obj2_a * obj2_t - obj2_b * sin(obj2_t));
 obj2_y =(int)(obj2_a - obj2_b * cos(obj2_t));
 obj2_y += 20;
 if (obj2_x < 1) {
 obj2_x = 1;
 }
 if (obj2_x > 78) {
 obj2_x = 78;
 }
 if (obj2_y < 2) {
 obj2_y = 2;
 }
 if (obj2_y > 38) {
 obj2_y = 38;
 }

 isCrash = mvwinch(win, obj2_y, obj2_x+1) != 0x20 || mvwinch(win, obj2_y, obj2_x-1) != 0x20 || mvwinch(win, obj2_y, obj2_x) != 0x20 || mvwinch(win, obj2_y-1, obj2_x) != 0x20 || mvwinch(win, obj2_y-1, obj2_x-1) != 0x20;
 if (isCrash == true) {
 mvwprintw(status, 0, 0, "[%d, %d] [%d, %d]", obj1_x, obj1_y, obj2_x, obj2_y);
 mvwprintw(status, 1, 0, "Crash !!!");
 break;
 }
 obj2_t += obj2_step;
 if (obj2_t > 30) {
 obj2_t = 0;
 }
 wmove(win,0,0);
 mvwprintw(status, 0, 0, "[%d, %d] [%d, %d]", obj1_x, obj1_y, obj2_x, obj2_y);
 wrefresh(win);
 wrefresh(status);
 usleep(100000);
 }
 wrefresh(status);
 getch();
 delwin(win);
 delwin(status);
 endwin();
 for (k = 0; k < obj1_size; ++k) {
 free(obj1_def[k]);
 }
 free(obj1_def);
 return 0;
}

核心修改说明

  1. 替换全局属性函数为窗口专属函数:
    将attron()/attroff()替换为wattron(win, ...)/wattroff(win, ...),确保颜色属性作用到目标窗口win上。

  2. 把绘制逻辑包裹在属性生效范围内:
    原代码仅在清除时设置颜色,绘制时属性已失效,现在将清除和绘制第二个对象的代码都放在wattron和wattroff之间,保证颜色生效。

  3. 修复逻辑笔误:
    原代码计算第二个对象位置时误用了obj1_t,改为obj2_t,让两个对象的运动逻辑独立。

  4. 新增终端兼容性检查:
    加入has_colors()和can_change_color()检查,提前排查终端不支持颜色的情况。

编译时记得链接ncurses库:

gcc your_code.c -o your_program -lncurses -lm

如果你想给第一个对象也设置颜色,只需要在调用drawObject()前添加wattron(win, COLOR_PAIR(你定义的颜色对编号)),调用后用wattroff取消即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:53:56