建议先看视频, www.douyin.com/video/76021… 要不然,或许,不太好理解,吧?
【场景:一片漆黑的终端屏幕,墨菲斯(就是那个叫
rocket的精灵)缓缓转过身,手里拿着几个大小不一的彩色圆球】
墨菲斯(画外音):
"这是你最后的机会。在这之后,就没有回头路了。如果你选择按Ctrl+C,故事结束,你在命令行里醒来,相信那些数据天生就是排好序的。但如果你选择编译运行...我会让你看看,冒泡排序的兔子洞有多深。"
【尼奥(也就是你)按下了回车键。突然,屏幕上炸开了一片彩虹】
墨菲斯:
"看好了,这些都C++结构体定义的是Node,每一个都是个小世界——里面有值(value),有位置(x),还有一个灵魂(Sprite* sp)。它们穿着不同颜色的衣服:红的、橙的、黄的...就像一群喝醉了酒、站成一排等待点名的小精灵。注意它们的身材——那个穿红衣服的,值只有30,瘦得像根筷子;那个穿紫衣服的,值200,胖得像个气球。"
【火箭精灵突然飞到画面中央,发出黄色的光芒】
墨菲斯:
"第一轮开始了...我们在遍历。看!左边这个胖子的值比右边大?交换! 看到了吗?不是瞬间移动,是慢一些的go(x,0)——它们真的在屏幕上滑步,像跳探戈一样互换位置。不只是屏幕上的动画,它们在内存里的datas数组中也 swap 了位置。这就是秩序的诞生,尼奥。"
【随着每一轮排序,火箭精灵都会大声报数】
墨菲斯:
"第二轮...第三轮...就像煮开水时气泡往上冒,最大的那个总是最先沉到右边。这就是冒泡排序的奥义——每一轮都会有一个'最大气泡'找到它的最终归宿。那些colors数组里的颜色?那只是为了让这场数字的华尔兹看起来更花哨一点。"
【最后,所有圆球整齐排列,从小到大,像军训过的士兵】
墨菲斯(收起光芒,写下最后一行字):
"演示完毕。你看,没有什么是真正混乱的,尼奥。只要有两层循环,一个if(datas[i]->value > datas[i+1]->value)的判断,再加上一点耐心(wait(1)),混沌就能变成秩序。现在...你还觉得矩阵只是0和1那么简单吗?"
【屏幕渐渐暗去,只留下一行小字:作者:李兴球】
简单说人话版:
这段代码就像是在电脑屏幕上搭了个舞台。它先用随机数造出5到8个彩色圆球(大小代表数值),然后让一个叫"火箭"的主持人一边报幕("第X轮开始啦"),一边指挥这些圆球玩"左边比右边大就换位子"的游戏。通过swap函数,圆球们不仅会交换数据,还会真的在屏幕上滑来滑去,让你肉眼看见冒泡排序是怎么把一堆乱序数字整理成一排的。最后所有圆球按大小站好队,火箭就说"下班啦",程序结束。
#include "sprites.h" //包含C++精灵库
using namespace std;
Sprite rocket; //建立角色叫rocket
struct Node{
int value,x; //值和坐标
Sprite *sp;
};
vector<Node *> datas;
vector<string> colors = {"red","orange","yellow","green",
"cyan","blue","purple","pink"};
void swap(int i,int j){ //交换两个节点
Node *a = datas[i];
Node *b = datas[j];
//交换a和b的x从标,并且到达自己的坐标
int tempx = a->x;
a->x = b->x;
b->x = tempx;
a->sp->go(a->x,0);
b->sp->go(b->x,0);
//在datas中的位置也要交换
Node *temp ;
temp = datas[i];
datas[i] = datas[j];
datas[j] = temp;
}
int main(){ //主功能块
g_screen->bgcolor("black");
int n= randint(5,8);
int x = 50-100*n/2; //最左边节点坐标(起始)
for(int i=0;i<n;i++){ //建立n个节点,放到datas中
int v = randint(30,200);
Node *node = new Node;
node->value = v;
node->x = x;
//按顺序选择索引为i的颜色,组合成角色的造型图片
string s = "res/circle_" + colors[i] + ".png";
Sprite *js = new Sprite(s); //新建角色,以s为造型
js->scale(v/100.0); //把角色缩小,要不然太大了
js->penup(); js->go(x,0); js->speed(1); //定好起始位置
node->sp = js; //节点包含有角色指针
datas.push_back(node);
x = x + 100; //每个节点相差100个单位
}
Sprite pen{"blank"};
pen.up().color(0).sety(300).write("冒泡排序算法可视化演示程序",50);
pen.color(30).sety(230).write("作者:李兴球,采用C++精灵库",30);
pen.color(60).sety(180).write("C++精灵库作者:李兴球",20);
rocket.wait(1).color("yellow").penup().sety(130).hide();
//真正的冒泡排序核心程序开始了
for(int j=1;j<n;j++){ //排序的核心程序在这里
string s = "第 " + to_string(j) + " 轮";
//删除最早写的文字,然后写上新的文字,并且等待1秒
rocket.cleartxts(1).write(s,42).wait(1);
for(int i=0;i<n-j;i++)
if(datas[i]->value > datas[i+1]->value ) //发现更大的,则交换
swap(i,i+1);
rocket.wait(1);
}
rocket.cleartxts(1).write("演示完毕!",42).done(); //完成了
return 0; //返回0
}