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

ncurses程序输入1后彩色条带重复显示问题排查

问题描述

开发的ncurses程序在main函数的while循环前会打印一条彩色条带;当用户输入1后,程序通过adjustedConstant()计算4种可见范围内的波长,对应颜色数组位置打印随机字符,其余位置输出空格。但实际运行时(编译参数-lncursesw,运行环境xfce4-terminal),输入1后条带会额外重复3次,共显示4条,而预期仅显示1条。输入1后输出的波长信息如下:

1n = 2, 2n = 3, Wavelength: 6.564696e-07 meters
1n = 2, 2n = 4, Wavelength: 4.862738e-07 meters
1n=2, 2n=5, Wavelength: 4.341730e-07 meters
1n=2, 2n=6, Wavelength: 4.102935e-07 meters

问题原因

核心问题出在内层波长计算循环的逻辑:当前代码每计算出一个可见波长,就完整打印一遍整条彩色条带。因为有4个可见波长,所以会触发4次条带打印,最终屏幕上出现4条重复内容。

修复方案

修改内层循环逻辑,先收集所有可见波长对应的索引,再一次性绘制条带,仅输出1条包含所有目标随机字符的彩色条带:

#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include <locale.h>
#include <math.h>

typedef struct {
  int r;
  int g;
  int b;
} RGB;

RGB newRGB(int r, int g, int b) {
  RGB color;
  color.r = r;
  color.g = g;
  color.b = b;
  return color;
}

void calculateColor(RGB *colors, int totalColors, int currentIndex, float saturation, float luminosity);
double adjustedConstant() {
  return 1.0973731568508E7 / (1 + 9.10938356E-31 / 1.67262192E-27);
}

int main() {
  setlocale(LC_ALL, "");

  int totalColors = 60;
  RGB colors[totalColors];
  float saturation = 1.0;
  float luminosity = 0.3;

  initscr();
  start_color();

  int end = totalColors - 18;
  int start = end - 42;
  for (int i = end; i >= start; i--) {
    calculateColor(&colors[i], totalColors, i, saturation, luminosity);

    // 转换RGB颜色为curses默认模型
    int r = colors[i].r * 1000 / 255;
    int g = colors[i].g * 1000 / 255;
    int b = colors[i].b * 1000 / 255;

    // 在curses中设置颜色
    init_color(i + 16, r, g, b);
    init_pair(i + 16, COLOR_BLACK, i + 16);

    // 打印初始彩色条带
    attron(COLOR_PAIR(i + 16));
    printw("  ");
    attroff(COLOR_PAIR(i + 16));
  }

  // 用于绘制的字符集合
  int characters[] = {
    9474, 9475, 10072, 10073, 12321
  };
  int numCharacters = sizeof(characters) / sizeof(characters[0]);

  while (1) {
    int number;
    printw("\n\nEnter 1 or -1 to exit: ");
    scanw("%d", &number);

    if (number == -1) {
      break;
    }

    // 收集所有可见波长对应的颜色索引
    int visibleIndices[10]; // 数组大小足够容纳所有可见波长
    int indexCount = 0;

    int n1 = 1, n2 = 2;
    double lambda_a = 0;
    while (1) {
      lambda_a = 1.0 / (adjustedConstant() * ((1.0 / (n1 * n1)) - (1.0 / (n2 * n2))));

      if (lambda_a >= 400E-9 && lambda_a <= 700E-9) {
        int index = (700 - lambda_a * 1e9) * (totalColors - 10.5) / (750 - 380);
        visibleIndices[indexCount++] = index;
      }
      if (lambda_a > 700E-9) {
        break;
      }
      n2++;
      if (n2 <= 6) {
        continue;
      }
      n1++;
      n2 = n1 + 1;
    }

    // 定位到初始条带下方(可选,避免覆盖原有内容)
    move(LINES - 3, 0);

    // 一次性绘制包含所有目标字符的条带
    for (int i = end; i >= start; i--) {
      attron(COLOR_PAIR(i + 16));
      // 检查当前索引是否属于可见波长位置
      int isVisible = 0;
      for (int j = 0; j < indexCount; j++) {
        if (i == visibleIndices[j]) {
          isVisible = 1;
          break;
        }
      }
      if (isVisible) {
        int randomCharacter = characters[rand() % numCharacters];
        wprintw(stdscr, "%lc ", randomCharacter); // 补空格对齐初始条带的双空格格式
      } else {
        printw("  ");
      }
      attroff(COLOR_PAIR(i + 16));
    }
    refresh();
  }
  getch();
  endwin();
  return 0;
}

void calculateColor(RGB *colors, int totalColors, int currentIndex, float saturation, float luminosity) {
  float hue = currentIndex * (360.0 / totalColors);
  float chroma = (1 - fabs(2 * luminosity - 1)) * saturation;
  float x = chroma * (1 - fabs(fmod(hue / 60, 2) - 1));
  float m = luminosity - chroma / 2;

  float r, g, b;
  if (hue >= 0 && hue < 60) {
    r = chroma;
    g = x;
    b = 0;
  } else if (hue >= 60 && hue < 120) {
    r = x;
    g = chroma;
    b = 0;
  } else if (hue >= 120 && hue < 180) {
    r = 0;
    g = chroma;
    b = x;
  } else if (hue >= 180 && hue < 240) {
    r = 0;
    g = x;
    b = chroma;
  } else if (hue >= 240 && hue < 300) {
    r = x;
    g = 0;
    b = chroma;
  } else {
    r = chroma;
    g = 0;
    b = x;
  }
  colors->r = (r + m) * 255;
  colors->g = (g + m) * 255;
  colors->b = (b + m) * 255;
}
关键修改点
  1. 新增索引收集逻辑:先遍历所有波长计算,将可见波长对应的颜色索引存入数组,不再每计算一个波长就打印一次条带。
  2. 统一绘制条带:遍历颜色条带时,检查当前索引是否在可见列表中,是则打印随机字符(补空格对齐初始格式),否则打印空格,仅执行一次完整条带绘制。
  3. 可选位置调整:用move()函数定位到屏幕下方,避免覆盖初始条带内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 16:45:55