从云课五秒钟到一秒钟之静态字符串与动态甜甜圈-2026-

往事

从云课五分钟到五秒钟焦虑的甜甜圈向前冲-CSDN博客


一秒钟

注:一秒钟是追求的目标。

静态字符串

rm -rf ~/donut && git clone -q https://gitcode.com/ZhangRelay1/donut.git && cd ~/donut && gcc helloworld.c -o helloworld && ./helloworld

动态甜甜圈

rm -rf ~/donut && echo "终端焦虑的甜甜圈" && git clone https://gitcode.com/ZhangRelay1/donut.git && cd ~/donut && g++ colordonut.cpp -o donut && ./donut && echo "突破封印的甜甜圈"

原版代码

字符串

#include <stdio.h>

int main() {
    // ANSI 颜色格式:\033[属性;颜色m 内容 \033[0m
    // 0m = 重置颜色,避免后续输出变色
    
    // 红色 Hello
    printf("\033[1;31mHello \033[0m");
    // 绿色 World
    printf("\033[1;32mWorld \033[0m");
    // 黄色 !
    printf("\033[1;33m!\033[0m\n");

    return 0;
}

甜甜圈

#include <stdio.h>
#include <math.h>
#include <cstring>
#include <unistd.h>
 
int main() {
    float A = 0, B = 0;
    float i, j;
    int k;
    float z[1760];
    char b[1760];
    printf("\x1b[2J");
    for (;;) {
        memset(b, 32, 1760);
        memset(z, 0, 7040);
        for (j = 0; j < 6.28; j += 0.07) {
            for (i = 0; i < 6.28; i += 0.02) {
                float c = sin(i);
                float d = cos(j);
                float e = sin(A);
                float f = sin(j);
                float g = cos(A);
                float h = d + 2;
                float D = 1 / (c * h * e + f * g + 5);
                float l = cos(i);
                float m = cos(B);
                float n = sin(B);
                float t = c * h * g - f * e;
                int x = 40 + 30 * D * (l * h * m - t * n);
                int y = 12 + 15 * D * (l * h * n + t * m);
                int o = x + 80 * y;
                int N = 8 * ((f * e - c * d * g) * m - c * d * e - f * g - l * d * n);
                if (22 > y && y > 0 && x > 0 && 80 > x && D > z[o]) {
                    z[o] = D;
                    b[o] = ".,-~:;=!*#$@"[N > 0 ? N : 0];
                }
            }
        }
        printf("\x1b[H");
        for (k = 0; k < 1761; k++) {
            putchar(k % 80 ? b[k] : 10);
            A += 0.00004;
            B += 0.00002;
        }
        usleep(30000);
    }
    return 0;
}

终端彩色 Hello + ASCII 旋转甜甜圈 全套完整讲解 & 一键运行方案

一、整体结构梳理

两套程序:

  1. 静态彩色 HelloWorld(C 语言):ANSI 终端彩色输出,无依赖数学库,极简
  2. 动态 3D ASCII 甜甜圈(C++):三角函数渲染圆环动画,终端字符绘制 3D 效果 配套两条一键执行单行 shell 命令,分别对应静态字符串 / 动态甜甜圈

二、静态彩色 helloworld.c 完整解析

源码回顾

c

运行

#include <stdio.h>

int main() {
    // ANSI 转义序列格式:\033[修饰符;前景色m 文本 \033[0m 重置样式
    // \033 等价 \x1b ESC转义字符,终端识别控制码
    
    // 1;31m:1=高亮加粗,31=红色前景
    printf("\033[1;31mHello \033[0m");
    // 1;32m 高亮绿色
    printf("\033[1;32mWorld \033[0m");
    // 1;33m 高亮黄色
    printf("\033[1;33m!\033[0m\n");

    return 0;
}

1. ANSI 颜色码对照表

表格

前景色代码样式标识
310 = 正常,1 = 加粗高亮
绿324 = 下划线
337 = 反色
34
35
36
37

\033[0m 必须加,重置所有颜色样式,否则终端后续输入文字都会带颜色。

2. 编译 & 运行命令

单行一键脚本(静态字符串)

bash

运行

git clone -q https://gitcode.com/ZhangRelay1/donut.git && cd ~/donut && gcc helloworld.c -o helloworld && ./helloworld

拆解分步说明:

  • git clone -q:静默克隆仓库,不输出多余日志
  • cd ~/donut:进入家目录下克隆的仓库文件夹
  • gcc helloworld.c -o helloworld:gcc 编译 C 程序,输出可执行文件 helloworld
  • ./helloworld:执行彩色打印程序

三、ASCII 3D 旋转甜甜圈 colordonut.cpp 深度讲解

核心原理

利用圆环参数方程 + 二维平面投影 + 光照明暗分级,把 3D 甜甜圈投射到 2D 终端字符画布,循环旋转两个角度 A、B 实现动画。

依赖头文件说明

cpp

运行

#include <stdio.h>   // 终端输出putchar/printf
#include <math.h>    // sin/cos三角函数,3D计算核心
#include <cstring>   // memset 内存初始化,C++标准头
#include <unistd.h>  // usleep 微秒延时,控制动画帧率
关键变量作用

cpp

运行

float A = 0, B = 0; // 两个旋转角度:A竖直旋转、B水平旋转,每次循环微量累加实现转动
float i, j;         // 圆环两层循环参数(大圆+小圆)
int k;
float z[1760];      // Z深度缓存:记录每个屏幕坐标的景深,近处覆盖远处
char b[1760];       // 终端字符画布缓冲区,80列×22行=1760字符
关键控制转义码

c

运行

printf("\x1b[2J"); // \x1b = \033,2J清空整个终端屏幕
printf("\x1b[H");  // 光标移动到左上角(0,0),实现画面刷新不滚动
双层循环:生成甜甜圈曲面

cpp

运行

for (j = 0; j < 6.28; j += 0.07) // 外层圆环大圆 0~2π
for (i = 0; i < 6.28; i += 0.02) // 小圆截面 0~2π

通过 sin/cos 计算三维坐标,经过 A、B 角度旋转矩阵变换,完成 3D 旋转。

透视投影 & 深度缓存

c

运行

float D = 1 / (c * h * e + f * g + 5); // 透视缩放系数,模拟近大远小
int x = 40 + 30 * D * (...); // 投影到屏幕X坐标(横向偏移缩放)
int y = 12 + 15 * D * (...); // 投影到屏幕Y坐标(纵向偏移缩放)
int o = x + 80 * y;          // 一维画布索引,二维坐标转一维数组下标

z[o] = D 深度缓冲逻辑:同一个屏幕像素只保留离镜头最近的点,避免画面重叠错乱。

明暗字符分级

c

运行

"N > 0 ? N : 0"
".,-~:;=!*#$@" // 字符从左到右亮度递增,模拟光照明暗

N 是光照强度,数值越大使用越密的字符,实现甜甜圈立体光影效果。

画面刷新与帧率控制

c

运行

usleep(30000); // 休眠30000微秒 = 30ms,控制动画流畅度
A += 0.00004;
B += 0.00002;  // 每次画面轻微增加旋转角度,持续转动

动态甜甜圈一键执行命令

bash

运行

echo "终端焦虑的甜甜圈" && git clone https://gitcode.com/ZhangRelay1/donut.git && cd ~/donut && g++ colordonut.cpp -o donut -lm && ./donut && echo "突破封印的甜甜圈"
重点补充编译参数 -lm

代码大量使用 math.h 数学函数,Linux 下 g++ 编译必须加 -lm 链接数学库,否则会报sin/cos未定义报错。 原命令缺少会编译失败,修正完整版:

bash

运行

echo "终端焦虑的甜甜圈" && git clone https://gitcode.com/ZhangRelay1/donut.git && cd ~/donut && g++ colordonut.cpp -o donut -lm && ./donut && echo "突破封印的甜甜圈"

四、踩坑避坑全通关指南

坑 1:git 重复克隆报错

如果已经克隆过仓库,再次执行会提示文件夹已存在,解决方案二选一:

  1. 执行前删除旧目录:

bash

运行

rm -rf ~/donut && echo "终端焦虑的甜甜圈" && git clone https://gitcode.com/ZhangRelay1/donut.git && cd ~/donut && g++ colordonut.cpp -o donut -lm && ./donut && echo "突破封印的甜甜圈"
  1. 仅进入目录不重新克隆:

bash

运行

cd ~/donut && g++ colordonut.cpp -o donut -lm && ./donut

坑 2:甜甜圈编译报错 undefined reference to sin/cos

原因:未链接数学库,编译参数缺少 -lm,修正:g++ colordonut.cpp -o donut -lm

坑 3:Windows 终端无颜色 / 无清屏效果

ANSI 转义码仅 Linux/macOS Terminal、WSL、GitBash 支持;CMD 原生不兼容。

坑 4:动画卡顿 / 过快

修改 usleep(30000) 数值:数字越大延时越长,动画越慢,如 usleep(50000) 变慢。

坑 5:退出甜甜圈动画

终端按下快捷键 Ctrl + C 终止程序。

五、两种程序对比总结

表格

项目helloworld.c 静态彩色字符串colordonut.cpp 动态甜甜圈
语言C 语言 gcc 编译C++ g++ 编译
依赖stdio.h 无额外库math.h 必须加 -lm 链接库
效果静态彩色文字,无动画实时 3D 旋转 ASCII 动画
原理ANSI 终端颜色控制码三维圆环参数方程 + 投影 + 深度缓存
资源占用极低持续循环计算,CPU 轻微占用

六、极简封装一键脚本(run_all.sh)

一次性整合静态 + 动态两种程序,按需执行

bash

运行

#!/bin/bash
rm -rf ~/donut
echo "=== 拉取代码仓库 ==="
git clone -q https://gitcode.com/ZhangRelay1/donut.git
cd ~/donut

echo -e "\n=== 运行静态彩色 HelloWorld ==="
gcc helloworld.c -o hello
./hello
rm -f hello

echo -e "\n=== 启动3D旋转甜甜圈动画 Ctrl+C退出 ==="
g++ colordonut.cpp -o donut -lm
./donut

授权运行:

bash

运行

chmod +x run_all.sh
./run_all.sh

Linux 终端 超多趣味一键运行案例(复制即跑,无需提前装环境,全单行命令)

前置说明

全部适配 Ubuntu / CentOS / WSL / MacOS 终端; Ctrl+C 退出动画;重复运行报错文件夹存在就加 rm -rf ~/funtmp 放最前面。

一、3D 旋转彩色甜甜圈(升级版带颜色,原版增强)

单行一键

bash

运行

rm -rf ~/donut && echo -e "\033[1;36m终端焦虑的彩色甜甜圈启动\033[0m" && git clone -q https://gitcode.com/ZhangRelay1/donut.git ~/donut && cd ~/donut && g++ colordonut.cpp -o donut -lm && ./donut && echo -e "\033[1;32m突破封印成功\033[0m"

二、终端下雪动画(纯 shell,不用编译,超浪漫)

一键单行

bash

运行

while true;do echo $LINES $COLUMNS $(for i in $(seq $RANDOM%$COLUMNS);do printf " ";done;echo '*')|awk '{system("clear");for(y=0;y<$1;y++){for(x=0;x<$2;x++){if(y==$3){printf "\033[1;37m*\033[0m"}else printf " "}print ""}}';sleep 0.1;done

三、终端爱心跳动(彩色动态爱心,表白神器)

C 语言一键编译运行单行

bash

运行

rm -rf ~/hearttmp && mkdir ~/hearttmp && cd ~/hearttmp && cat > heart.c <<EOF
#include <stdio.h>
#include <math.h>
#include <unistd.h>
int main(){
    float x,y,a;
    for(;;){
        for(y=1.5f;y>-1.5f;y-=0.1f){
            for(x=-1.5f;x<1.5f;x+=0.05f){
                a=x*x+y*y-1;
                if(a*a*a-x*x*y*y*y<0)printf("\033[1;31m*\033[0m");
                else printf(" ");
            }printf("\n");
        }
        usleep(100000);
        printf("\033[H");
    }
    return 0;
}
EOF
gcc heart.c -o heart -lm && ./heart

四、黑客帝国数字雨(绿色字符流,装 X 神器)

纯 bash 无需编译,一键运行:

bash

运行

while :;do echo $LINES $COLUMNS $((RANDOM%2));sleep 0.05;done|awk '{system("clear");for(i=0;i<$1;i++){for(j=0;j<$2;j++){c=rand()*10;if($3==1&&rand()>0.97)printf("\033[1;32m%d\033[0m",c);else printf " "}print ""}}'

五、终端贪吃蛇游戏(C 语言完整版,方向键操控)

一键自动生成代码 + 编译 + 启动:

bash

运行

rm -rf ~/snaketmp && mkdir ~/snaketmp && cd ~/snaketmp && cat > snake.c <<EOF
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <termios.h>
#include <signal.h>
int width=20,height=20;
int x,y,fx,fy,score;
int tx[400],ty[400];
int len;
char dir='d';
struct termios old;
void setterm(){tcgetattr(0,&old);struct termios n=old;n.c_lflag&=~(ICANON|ECHO);tcsetattr(0,TCSANOW,&n);}
void resterm(){tcsetattr(0,TCSANOW,&old);}
void genfood(){fx=rand()%width;fy=rand()%height;}
void draw(){
    system("clear");
    for(int i=0;i<width+2;i++)printf("#");printf("\n");
    for(int i=0;i<height;i++){
        for(int j=0;j<width;j++){
            if(j==0)printf("#");
            if(i==y&&j==x)printf("\033[1;32mO\033[0m");
            else if(i==fy&&j==fx)printf("\033[1;31mF\033[0m");
            else {int hit=0;for(int k=1;k<len;k++)if(tx[k]==j&&ty[k]==i){printf("\033[1;34mo\033[0m");hit=1;break;}if(!hit)printf(" ");}
            if(j==width-1)printf("#");
        }printf("\n");
    }
    for(int i=0;i<width+2;i++)printf("#");printf("\n得分:%d\nWASD控制,Q退出",score);
}
void input(){
    if(kbhit()){char c=getchar();if(c=='a'&&dir!='d')dir='a';if(c=='d'&&dir!='a')dir='d';if(c=='w'&&dir!='s')dir='w';if(c=='s'&&dir!='w')dir='s';if(c=='q'){resterm();exit(0);}}
}
int kbhit(){struct timeval t={0,0};fd_set f;FD_ZERO(&f);FD_SET(0,&f);return select(1,&f,NULL,NULL,&t);}
void logic(){
    int px=tx[len-1],py=ty[len-1];
    for(int i=len-1;i>0;i--){tx[i]=tx[i-1];ty[i]=ty[i-1];}
    if(dir=='a')x--;if(dir=='d')x++;if(dir=='w')y--;if(dir=='s')y++;
    if(x<0||x>=width||y<0||y>=height){resterm();printf("游戏结束!得分:%d\n",score);exit(0);}
    for(int i=1;i<len;i++)if(tx[i]==x&&ty[i]==y){resterm();printf("撞到自己!得分:%d\n",score);exit(0);}
    tx[0]=x;ty[0]=y;
    if(x==fx&&y==fy){score+=10;len++;tx[len-1]=px;ty[len-1]=py;genfood();}
}
int main(){
    setterm();srand(time(NULL));x=width/2;y=height/2;genfood();tx[0]=x;ty[0]=y;len=1;score=0;
    while(1){draw();input();logic();usleep(100000);}
    return 0;
}
EOF
gcc snake.c -o snake && ./snake

操作:W A S D 上下左右,Q 退出

六、终端 2048 小游戏(一键生成运行)

bash

运行

rm -rf ~/game2048 && mkdir ~/game2048 && cd ~/game2048 && cat > 2048.c <<EOF
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<unistd.h>
int mp[4][4];
void init(){
    for(int i=0;i<4;i++)for(int j=0;j<4;j++)mp[i][j]=0;
    srand((unsigned)time(NULL));
    int a=rand()%4,b=rand()%4,c=rand()%4,d=rand()%4;
    mp[a][b]=2;mp[c][d]=4;
}
void show(){
    system("clear");
    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++)printf("%4d",mp[i][j]);
        printf("\n");
    }
    printf("W上 S下 A左 D右\n");
}
void randadd(){
    int x[16],y[16],cnt=0;
    for(int i=0;i<4;i++)for(int j=0;j<4;j++)if(mp[i][j]==0){x[cnt]=i;y[cnt]=j;cnt++;}
    if(cnt==0)return;
    int r=rand()%cnt;
    mp[x[r]][y[r]]=rand()%2?2:4;
}
void left(){
    for(int i=0;i<4;i++){
        int t[4]={0},p=0;
        for(int j=0;j<4;j++)if(mp[i][j]!=0)t[p++]=mp[i][j];
        for(int j=0;j<3;j++)if(t[j]==t[j+1]&&t[j]!=0){t[j]*=2;t[j+1]=0;}
        int tp=0;for(int j=0;j<4;j++)if(t[j]!=0)mp[i][tp++]=t[j];else mp[i][tp++]=0;
    }
    randadd();
}
void right(){for(int i=0;i<4;i++){int t[4]={0},p=3;for(int j=3;j>=0;j--)if(mp[i][j])t[p--]=mp[i][j];for(int j=0;j<3;j++)if(t[j]==t[j+1]&&t[j]){t[j]*=2;t[j+1]=0;}int tp=3;for(int j=3;j>=0;j--)if(t[j])mp[i][tp--]=t[j];else mp[i][tp--]=0;}randadd();}
void up(){for(int j=0;j<4;j++){int t[4]={0},p=0;for(int i=0;i<4;i++)if(mp[i][j])t[p++]=mp[i][j];for(int i=0;i<3;i++)if(t[i]==t[i+1]&&t[i]){t[i]*=2;t[i+1]=0;}int tp=0;for(int i=0;i<4;i++)if(t[i])mp[tp++][j]=t[i];else mp[tp++][j]=0;}randadd();}
void down(){for(int j=0;j<4;j++){int t[4]={0},p=3;for(int i=3;i>=0;i--)if(mp[i][j])t[p--]=mp[i][j];for(int i=0;i<3;i++)if(t[i]==t[i+1]&&t[i]){t[i]*=2;t[i+1]=0;}int tp=3;for(int i=3;i>=0;i--)if(t[i])mp[tp--][j]=t[i];else mp[tp--][j]=0;}randadd();}
int main(){
    char op;init();
    while(1){show();op=getchar();
        if(op=='a')left();if(op=='d')right();if(op=='w')up();if(op=='s')down();
    }
    return 0;
}
EOF
gcc 2048.c -o game2048 && ./game2048

七、终端时钟(彩色动态电子表)

bash

运行

while true;do clear;t=$(date "+%H:%M:%S");echo -e "\033[1;35m==== $t ====\033[0m";sleep 1;done

八、彩虹文字刷屏(彩色滚动横幅)

bash

运行

text="Linux终端趣味一键案例";while true;do for c in 31 32 33 34 35 36 37;do echo -e "\033[1;${c}m$text\033[0m";sleep 0.1;clear;done;done

使用小贴士

  1. 想清空残留文件夹:命令开头加 rm -rf ~/xxx(xxx 对应目录名 donut/hearttmp/snaketmp)
  2. 退出所有动画 / 游戏:Ctrl + C
  3. 编译报错找不到 math 函数:编译命令必须带 -lm
  4. WSL / Mac 全部兼容;纯 Windows CMD 无彩色效果,建议用 Windows Terminal

本文介绍了两种有趣的终端程序实现:静态彩色Hello World和动态3D ASCII甜甜圈动画。文章详细解析了二者的代码原理,包括ANSI转义序列实现终端彩色输出、3D渲染算法以及终端动画控制技术。同时提供了完整的一键运行脚本,并对常见问题进行了解答。此外,还延伸介绍了多种终端趣味程序,如下雪动画、爱心跳动、贪吃蛇游戏等,均附有可直接执行的单行命令。文中强调了对数学库的链接(-lm)和终端兼容性等关键注意事项,为读者提供了完整的终端趣味编程实践方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangrelay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值