ASCII T恤艺术代码优化及前4行梯形可视化实现咨询
ASCII T恤图案代码优化与梯形可视化实现
问题背景
我用C语言实现了一个ASCII格式的T恤图案生成函数,目前是逐行判断绘制,但代码冗余度很高。想优化代码结构让它更简洁,同时想把图案的前4行拆分为两个独立的梯形(左右肩部/袖子区域),请教具体实现方法。原代码如下:
原实现代码
void displayShirt(char size, char neckline, char leftsleeve, char leftChest, char rightSleeve, char rightChest, char bottomLeft, char bottomRight) { int isRound; int halfColumn; int r; int c; int rows, columns; switch (size) { case 'S': rows = 10; columns = 18; break; case 'M': rows = 12; columns = 22; break; case 'L': rows = 14; columns = 26; break; case 'X': rows = 16; columns = 30; break; } halfColumn = columns / 2; switch (neckline) { case 'R': isRound = 1; break; case 'V': isRound = 0; break; } printf("\n\nMock Shirt:\n"); for (r = 1; r <= rows; r++) { for (c = 0; c <= columns; c++) { if (r == 1) { if (c >= 0 && c <= 3) printf(" "); else if ( (c == 4 || (c <= halfColumn - 2 || c >= halfColumn + 3)) && (c <= columns - 3)) printf("x"); else printf(" "); } else if (r == 2) { if ((isRound == 1) && (c == halfColumn || c == halfColumn + 1 )) printf("x"); else if (c == 3 || c == halfColumn - 1 || c == halfColumn + 2 || c == columns - 2) printf("x"); else printf(" "); } else if (r == 3) { if (c == 2) printf("x"); else if (c == 4 && (rightSleeve == 'L' || rightSleeve == 'P')) printf("%c", rightSleeve); else if ((isRound == 0) && (c == halfColumn || c == halfColumn + 1)) printf("x"); else if (c == columns - 3 && (leftsleeve == 'L' || leftsleeve == 'P')) printf("%c", leftsleeve); else if (c == columns - 1) printf("x"); else printf(" "); } else if (r == 4) { if (c >= 1 && c <= 4) printf("x"); else if (c == 6 && (rightChest == 'L' || rightChest == 'P' || rightChest == 'O')) printf("%c", rightChest); else if (c == columns - 5 && (leftChest == 'L' || leftChest == 'P' || leftChest == 'O')) printf("%c", leftChest); else if (c >= columns - 3 && c <= columns) printf("x"); else printf(" "); } else if ((r >= 5 || r > rows) && ((c == 4 || c == columns - 3) || (r == rows && (c >= 4 && c <= columns - 3)))) printf("x"); else if (r == rows - 1 && c == 6 && bottomRight == 'O') printf("%c", bottomRight); else if (r == rows - 1 && c == columns - 5 && bottomLeft == 'O') printf("%c", bottomLeft); else printf(" "); } printf("\n"); } } int main() { char size = 'M'; char neckline = 'V'; char leftSleeve = 'L'; char leftChest = 'O'; char rightSleeve = 'O'; char rightChest = 'O'; char bottomLeft = 'O'; char bottomRight = 'O'; displayShirt(size, neckline, leftSleeve, leftChest, rightSleeve, rightChest, bottomLeft, bottomRight); size = 'X'; neckline = 'R'; leftSleeve = 'P'; leftChest = 'L'; rightSleeve = 'L'; rightChest = 'O'; bottomLeft = 'O'; bottomRight = 'O'; displayShirt(size, neckline, leftSleeve, leftChest, rightSleeve, rightChest, bottomLeft, bottomRight); return 0; }
优化思路与梯形实现方案
核心优化方向
- 用数据结构替代冗余switch:把尺寸对应的行列数存入结构体数组,避免重复分支判断,新增尺寸只需修改数组。
- 抽象左右梯形结构:前4行的左右两侧是对称梯形,每行的列范围有固定规律,用函数封装梯形的判断逻辑,替代逐列的if嵌套。
- 分离基础形状与装饰元素:把领口、袖子/胸口的装饰字符和T恤基础轮廓绘制逻辑分开,让代码职责更清晰。
梯形具体实现逻辑
前4行的左右梯形列范围规律如下:
| 行号 | 右侧梯形列范围 | 左侧梯形列范围 |
|---|---|---|
| 1 | 4~4 | columns-3~columns-3 |
| 2 | 3~3 | columns-2~columns-2 |
| 3 | 2~2 | columns-1~columns-1 |
| 4 | 1~4 | columns-3~columns |
通过两个辅助函数isRightTrapezoid和isLeftTrapezoid判断当前行列是否属于对应梯形,再结合装饰字符的位置逻辑完成绘制。
重构后的优化代码
#include <stdio.h> #include <stdbool.h> // 尺寸参数结构体,替代原switch分支 typedef struct { char size; int rows; int columns; } ShirtSize; ShirtSize sizeMap[] = { {'S', 10, 18}, {'M', 12, 22}, {'L', 14, 26}, {'X', 16, 30} }; int sizeCount = sizeof(sizeMap)/sizeof(sizeMap[0]); // 获取指定尺寸对应的行列参数 void getSizeParams(char size, int *rows, int *columns) { for(int i=0; i<sizeCount; i++){ if(sizeMap[i].size == size){ *rows = sizeMap[i].rows; *columns = sizeMap[i].columns; return; } } // 默认返回M号参数 *rows = 12; *columns = 22; } // 判断当前位置是否属于右侧梯形区域 bool isRightTrapezoid(int r, int c, int columns) { switch(r){ case 1: return c == 4; case 2: return c == 3; case 3: return c == 2; case 4: return c >=1 && c <=4; default: return false; } } // 判断当前位置是否属于左侧梯形区域 bool isLeftTrapezoid(int r, int c, int columns) { switch(r){ case 1: return c == columns -3; case 2: return c == columns -2; case 3: return c == columns -1; case 4: return c >= columns -3 && c <= columns; default: return false; } } void displayShirt(char size, char neckline, char leftSleeve, char leftChest, char rightSleeve, char rightChest, char bottomLeft, char bottomRight) { int rows, columns; getSizeParams(size, &rows, &columns); int halfColumn = columns / 2; bool isRound = (neckline == 'R'); printf("\n\nMock Shirt:\n"); for (int r = 1; r <= rows; r++) { for (int c = 0; c <= columns; c++) { char drawChar = ' '; // 绘制左右梯形及对应装饰 if(isRightTrapezoid(r, c, columns)){ if(r ==3 && c ==4 && (rightSleeve == 'L' || rightSleeve == 'P')){ drawChar = rightSleeve; } else if(r ==4 && c ==6 && (rightChest == 'L' || rightChest == 'P' || rightChest == 'O')){ drawChar = rightChest; } else { drawChar = 'x'; } } else if(isLeftTrapezoid(r, c, columns)){ if(r ==3 && c == columns -3 && (leftSleeve == 'L' || leftSleeve == 'P')){ drawChar = leftSleeve; } else if(r ==4 && c == columns -5 && (leftChest == 'L' || leftChest == 'P' || leftChest == 'O')){ drawChar = leftChest; } else { drawChar = 'x'; } } // 绘制领口区域 else if(r <=3){ if(r ==2 && isRound && (c == halfColumn || c == halfColumn +1)){ drawChar = 'x'; } else if(r ==3 && !isRound && (c == halfColumn || c == halfColumn +1)){ drawChar = 'x'; } else if(r ==2 && (c == halfColumn -1 || c == halfColumn +2)){ drawChar = 'x'; } } // 绘制衣身主体及底部装饰 else if(r >=5){ if(c ==4 || c == columns -3){ drawChar = 'x'; } else if(r == rows && c >=4 && c <= columns -3){ drawChar = 'x'; } else if(r == rows -1){ if(c ==6 && bottomRight == 'O') drawChar = bottomRight; else if(c == columns -5 && bottomLeft == 'O') drawChar = bottomLeft; } } printf("%c", drawChar); } printf("\n"); } } int main() { char size = 'M'; char neckline = 'V'; char leftSleeve = 'L'; char leftChest = 'O'; char rightSleeve = 'O'; char rightChest = 'O'; char bottomLeft = 'O'; char bottomRight = 'O'; displayShirt(size, neckline, leftSleeve, leftChest, rightSleeve, rightChest, bottomLeft, bottomRight); size = 'X'; neckline = 'R'; leftSleeve = 'P'; leftChest = 'L'; rightSleeve = 'L'; rightChest = 'O'; bottomLeft = 'O'; bottomRight = 'O'; displayShirt(size, neckline, leftSleeve, leftChest, rightSleeve, rightChest, bottomLeft, bottomRight); return 0; }
优化点说明
- 用结构体数组存储尺寸参数,新增尺寸时无需修改绘制逻辑,扩展性更强。
- 抽象梯形判断函数,把前4行的重复逻辑提取出来,大幅减少嵌套if的数量。
- 变量命名更直观(如用
bool类型替代int的isRound),代码可读性提升。 - 分离装饰字符与基础轮廓的绘制逻辑,每个模块职责单一,便于后续维护。
内容的提问来源于stack exchange,提问作者Rommel Legaspi
相关产品推荐
相关产品推荐

