为什么彩色丝带在输出中重复多次

问题描述 投票:0回答:2

main 中的代码在一段时间内打印一条彩色丝带,当我尝试在用户输入 1 后的一段时间内重复此过程时,该常数会调整可见光中可能的波长(即四个),并将一个字符分配给根据 o 形状的波长指定阵列的位置,否则打印其他颜色的空白空间。

Result:

恰巧用户通知1后,在第一次之后又重复了3次,如上面结果的打印,只需要打印一条色带。是什么让它发生? 编译

-lncursesw
环境
xfce4-terminal

我认为这是因为
wprintw(stdscr, "%lc", randomCharacter);
,我注意到每个新条带都包含在不同位置绘制的
randomCharacter
,对应于
adjustedConstant
的四种可能长度之一,因此总共有 4 个条带,而不是 1 个。
i == index
这是一种可视化与可见光谱内特定波长相关的颜色的方法。
当用户输入 -1 以外的值时,程序将使用
adjustedConstant
给出的公式计算与给定输入相关的波长。如果该波长在可见光范围内(400 nm 到 700 nm 之间),则程序会确定颜色数组中的相应位置,并打印与该波长相关的颜色的随机字符。
按下时 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
#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);

    // Convert RGB colors to curses default model
    int r = colors[i].r * 1000 / 255;
    int g = colors[i].g * 1000 / 255;
    int b = colors[i].b * 1000 / 255;

    // Set color in curses
    init_color(i + 16, r, g, b); // needs to define the pair of colors i+16
    init_pair(i + 16, COLOR_BLACK, i + 16);

    // Print the color
    attron(COLOR_PAIR(i + 16)); // needs to activate the pair of colors i+16
    printw("  ");
    attroff(COLOR_PAIR(i + 16));
  }

  // Vector of characters for drawing
  int characters[] = {
    9474, 9475, 10072, 10073, 12321
  };
  int numCharacters = sizeof(characters) / sizeof(characters[0]);

  // Loop to print the colors on the screen
  int wavelength;
  while (1) {
    int number;
    printw("\n\nEnter 1 or -1 to exit: ");
    scanw("%d", &number);

    if (number == -1) {
      break; // Exit the loop if the user enters -1
    }

    // Wavelength
    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) {

        // Calculate the position in the colors array based on the wavelength
        int index = (700 - lambda_a * 1e9) * (totalColors - 10.5) / (750 - 380);
        // Print all colors
        for (int i = end; i >= start; i--) {
          if (i == index) {
            // Activate the color pair for the corresponding wavelength color
            attron(COLOR_PAIR(i + 16));
            // Draw one of the characters randomly
            int randomCharacter = characters[rand() % numCharacters];
            wprintw(stdscr, "%lc", randomCharacter);
            // Deactivate the color pair
            attroff(COLOR_PAIR(i + 16));
          } else {
            // Draw empty spaces for the other colors
            attron(COLOR_PAIR(i + 16));
            printw("  ");
            attroff(COLOR_PAIR(i + 16));
          }
        }
        refresh(); // Update the screen
      }
      if (lambda_a > 700E-9) {
        break; // Wavelength exceeded the visible range, end the loop
      }
      n2++; // Increment the value of 2n
      if (n2 <= 6) {
        continue;
      }
      n1++; // Increment the value of 1n and reset 2n to a value greater than 1n
      n2 = n1 + 1;
    }
  }
  getch(); // Wait for user input
  endwin(); // End curses mode
  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;
}
c ncurses
2个回答
0
投票

发布的代码中的循环逻辑不正确。

OP 代码具有一个计算可能与光谱吸收线相对应的

lambda_a
值的外循环,以及一个根据与
lambda_a
值关联的颜色索引以块或字符形式打印色谱的内循环。内部循环打印色谱并检查与
lambda_a
关联的索引是否匹配,在这种情况下打印字符,然后在外部循环中修改
lambda_a
。通过此过程,四个
lambda_a
值出现在可见光谱范围 (
lambda_a >= 400E-9 && lambda_a <= 700E-9
) 中,因此光谱被打印四次。

更好的方法是计算并缓存与吸收线匹配的颜色索引。然后,当色谱打印一次时,如果颜色索引与缓存索引匹配,则会打印字符。

这里是实现此功能的 OP 代码的修改版本。现在有一个循环,根据原始 OP 代码使用吸收线的颜色索引填充

line_idxs
。接下来是打印光谱的循环。请注意,此代码以相反的顺序逐步执行
line_idxs
,因为颜色的打印顺序是从最高索引到最低索引,而吸收线是按从最低到最高顺序发现的。

#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(void) {
    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);

        // Convert RGB colors to curses default model
        int r = colors[i].r * 1000 / 255;
        int g = colors[i].g * 1000 / 255;
        int b = colors[i].b * 1000 / 255;

        // Set color in curses
        init_color(i + 16, r, g, b); // needs to define the pair of colors i+16
        init_pair(i + 16, COLOR_BLACK, i + 16);

        // Print the color
        attron(COLOR_PAIR(i + 16)); // needs to activate the pair of colors i+16
        printw("  ");
        attroff(COLOR_PAIR(i + 16));
    }

    // Vector of characters for drawing
    int characters[] = {
        9474, 12321
    };
    int numCharacters = sizeof(characters) / sizeof(characters[0]);

    // Loop to print the colors on the screen
    // int wavelength;
    while (1) {
        int number;
        printw("\n\nEnter 1 or -1 to exit: ");
        scanw("%d", &number);

        if (number == -1) {
            break; // Exit the loop if the user enters -1
        }

        // Wavelength
        int n1 = 1, n2 = 2;
        int line_idxs[4] = { 0 };  // Save spectral line indices.

        // Populate `line_idxs[]` with spectral lines.
        for(size_t i = 0; i < 4;) {
            double lambda_a = 0;
            lambda_a =(1.0 / (adjustedConstant() * ((1.0 / (n1 * n1)) - (1.0 / (n2 * n2)))));
            if (lambda_a >= 400E-9 && lambda_a <= 700E-9) {
                line_idxs[i] = start + (700 - lambda_a * 1e9) * (totalColors - 10.5) / (750 - 380);
                i++;
            }
            n2++;
            if (n2 <= 6) continue;
            n1++;
            n2 = n1 + 1;
        }

        // Print spectrum.
        for (int i = end, line_idx = 3; i >= start; i--) {
            attron(COLOR_PAIR(i + 16));
            if (line_idx >= 0 && i == line_idxs[line_idx]) {
                // Print a random character.
                int randomCharacter = characters[rand() % numCharacters];
                wprintw(stdscr, "%lc", randomCharacter);
                --line_idx;
            } else {
                printw("  ");
            }
            attroff(COLOR_PAIR(i + 16));
        }
        refresh(); // Update the screen
    }
    getch(); // Wait for user input
    endwin(); // End curses mode

    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;
}

这是结果显示:


0
投票

功能区被打印多次,因为外循环的条件在 4 次迭代中保持为真。

您应该在色带循环后输出一个

'\n'
,以便所有色带显示对齐而不是垂直对齐,而不是长的缠绕色带。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.