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

ASCII符号旋转方块字符丢失问题求助

解决终端方块旋转时字符消失的问题

问题根源

  • 坐标累积误差:每次旋转直接修改coords_data中的坐标,多次旋转后浮点取整的误差会导致多个点重叠到同一坐标,最终只剩圆形(重复旋转后点不断向中心聚集)。
  • 角度逻辑错误:main函数中angle += i * angle_mult会让旋转角度增量越来越大,且rotate(angle)是让点旋转累积的总角度,而非单次增量,导致旋转逻辑完全错误。
  • 点丢失问题:部分点旋转后越界被直接丢弃,且没有保留原始坐标,导致后续旋转无法恢复这些点。

修复方案

  1. 保存方块的原始初始坐标,每次旋转都基于原始坐标计算新位置,彻底避免累积误差。
  2. 修正角度更新逻辑,每次旋转固定的增量角度,保持匀速旋转。
  3. 调整旋转函数逻辑,不再修改原始坐标,仅临时计算旋转后的位置并更新显示区域。

修改后的完整代码

#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>

#define SIZE 100   // size of the field of characters
#define SQ_SIZE 10 // size of the square

char field[SIZE][SIZE] = {' '};
char fill_char = ' ';
char sq_char = '.';

typedef struct Coords {
  int x;
  int y;
} Coords;

// 保存方块的原始初始坐标(固定不变)
Coords original_coords[SQ_SIZE][SQ_SIZE];
// 保存当前旋转后的坐标(仅用于显示,每次旋转重新计算)
Coords current_coords[SQ_SIZE][SQ_SIZE];

// prints the field
// grid was used for debugging
void print_field(bool show_grid) {

  if (show_grid) {
    printf("\033[32;1m   ");
    for (int i = 0; i < SIZE; i++)
      printf("%3d", i);
    printf("\n\033[0m");
  }

  for (int i = 0; i < SIZE; i++) {
    if (show_grid)
      printf("\033[32;1m%3d\033[0m", i);
    for (int j = 0; j < SIZE; j++) {
      printf("%3c", field[i][j]);
    }
    printf("\n");
  }
}

// fills the entire field with fill_char
void fill_field(void) {
  for (int i = 0; i < SIZE; i++)
    for (int j = 0; j < SIZE; j++)
      field[i][j] = fill_char;
}

// creates the square and fill the original_coords with square's points' coords
void init_square(void) {
  int start_x = SIZE / 2 - SQ_SIZE / 2;
  int start_y = SIZE / 2 - SQ_SIZE / 2;

  for (int i = 0; i < SQ_SIZE; i++)
    for (int j = 0; j < SQ_SIZE; j++) {
      original_coords[i][j].x = start_x + i;
      original_coords[i][j].y = start_y + j;
      current_coords[i][j] = original_coords[i][j];
      field[original_coords[i][j].x][original_coords[i][j].y] = sq_char;
    }
}

// changes the coords using the transition matrix
void calculate_rotated_coords(Coords *dest, const Coords *src, double rad, int center_x, int center_y) {
  int x = src->x - center_x;
  int y = src->y - center_y;

  double new_x_double = x * cos(rad) - y * sin(rad);
  double new_y_double = x * sin(rad) + y * cos(rad);

  dest->x = round(new_x_double) + center_x;
  dest->y = round(new_y_double) + center_y;
}

// rotates the square
void rotate(double rad) {
  int center_x = SIZE / 2;
  int center_y = SIZE / 2;

  fill_field();

  // 基于原始坐标计算旋转后的新位置
  for (int i = 0; i < SQ_SIZE; i++) {
    for (int j = 0; j < SQ_SIZE; j++) {
      calculate_rotated_coords(&current_coords[i][j], &original_coords[i][j], rad, center_x, center_y);

      // Ensure new coordinates are within bounds
      if (current_coords[i][j].x >= 0 && current_coords[i][j].x < SIZE &&
          current_coords[i][j].y >= 0 && current_coords[i][j].y < SIZE) {
        field[current_coords[i][j].x][current_coords[i][j].y] = sq_char;
      }
    }
  }
}

int main(void) {
  fill_field();
  init_square();

  printf("\n\n");
  const double angle_step = M_PI / 24; // 每次旋转的增量角度(更小更平滑)
  double current_angle = 0;

  while (true) {
    rotate(current_angle);
    current_angle += angle_step;
    // 角度超过2π后重置,避免数值过大
    if (current_angle >= 2 * M_PI) {
      current_angle -= 2 * M_PI;
    }

    printf("\033[s");
    printf("\033[1;32m");
    print_field(false);
    printf("\033[0m");
    printf("\033[u\033[2J");
    usleep(100000); // 调整休眠时间,让动画更流畅
  }

  return 0;
}

关键修改说明

  • 分离原始与当前坐标:新增original_coords存储方块初始位置,永远不修改;current_coords仅存储每次旋转后的临时坐标,每次旋转都从原始坐标重新计算,彻底消除累积误差。
  • 修正角度逻辑:main中每次旋转固定增量angle_step,并在角度超过2π后重置,保持匀速且数值稳定。
  • 优化旋转计算:将坐标计算逻辑拆分为calculate_rotated_coords,更清晰,且避免直接修改原始数据。
  • 调整动画参数:缩小角度增量并减少休眠时间,让旋转动画更平滑自然。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 06:14:50