ASCII符号旋转方块字符丢失问题求助
解决终端方块旋转时字符消失的问题
问题根源
- 坐标累积误差:每次旋转直接修改
coords_data中的坐标,多次旋转后浮点取整的误差会导致多个点重叠到同一坐标,最终只剩圆形(重复旋转后点不断向中心聚集)。 - 角度逻辑错误:
main函数中angle += i * angle_mult会让旋转角度增量越来越大,且rotate(angle)是让点旋转累积的总角度,而非单次增量,导致旋转逻辑完全错误。 - 点丢失问题:部分点旋转后越界被直接丢弃,且没有保留原始坐标,导致后续旋转无法恢复这些点。
修复方案
- 保存方块的原始初始坐标,每次旋转都基于原始坐标计算新位置,彻底避免累积误差。
- 修正角度更新逻辑,每次旋转固定的增量角度,保持匀速旋转。
- 调整旋转函数逻辑,不再修改原始坐标,仅临时计算旋转后的位置并更新显示区域。
修改后的完整代码
#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(¤t_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
相关产品推荐
相关产品推荐

