同学!你见过会“流血”的算法吗?C++深搜遍历图的每条路径可视化程序!

你知道吗?最近我在抖音上刷到一个超燃的视频(号:pxcoding),背景音乐是那首经典的《燃烧的火焰》——对,就是日本《排球女将》的主题曲,一下子就把人拉回了那个热血的70/80年代。
但画面里演的不是小鹿纯子扣球,而是一颗蓝色的小火箭,在黑色背景上嗖嗖地飞,身后拖着红色的尾巴,像血液在血管里流淌一样,从一个点流到另一个点。这就是用C++精灵库(sprites.h)写的一个程序——让它自动找出从A点到C点的所有路径。
这玩意儿到底在搞什么?
简单来说,就是这个C++程序运行后会生成了A、B、C、D、E五个点,把它们两两相连,做成一张网。然后小火箭从A出发,要去C,它要尝试每一条可能的路。最酷的是,这不是枯燥的代码运行,而是一场视觉盛宴:
当小火箭决定前往下一个邻居节点时,它的画笔颜色会变成红色(HSV颜色模式里的H=0,表示颜色的色相为0,即红色),然后放慢速度(speed(1)),缓缓爬过去,真的就像鲜血在黑色的血管网络里缓缓流淌。到了之后,它恢复原速,停顿半秒,让你看清楚它的轨迹。如果走不通?没关系,它开始"时光倒流"——画笔颜色变成青色,以同样的速度缓缓退回去,就像血液回流一样。这种回溯的过程,其实就是计算机里经典的深度优先搜索(DFS)算法的可视化。
你看代码里这段:
visitor.color(0).speed(1).go(nb).speed(0).wait(0.5);
简单几行,就把冷冰冰的算法变成了看得见的"血液流动"。你可能会问,C++精灵库默认的角色为什么是小火箭?🚀
这可不是随便选的。你想啊,小火箭代表着什么?冲破大气层,冲向星辰大海!这库的设计者用心了——它就是给少年们准备的最好的礼物。
说到这,我就想起了最近中国科学院大学成立星际航行学院的新闻。看着屏幕上的小火箭在图结构中穿梭寻找路径,不正是象征着我们这些正值年少的同学们吗?精力旺盛,充满好奇,在知识的网络中探索每一条可能的路径,为了明天的星辰大海做准备。

很多人以为学编程就是对着黑框框(命令行)敲枯燥的代码。但C++精灵库完全打破了这种印象:可视化即时反馈:你写的不是抽象的逻辑,而是看得见的小精灵在屏幕上跳舞。
而且这玩意儿真有学习价值!你在玩的过程中,不知不觉就理解了图的遍历、递归回溯、深度优先搜索这些大学数据结构课的核心概念。等真到了课堂上,你脑子里想的不是"vis数组标记访问状态",而是"小火箭变红又变青,血液流过去又流回来"。
同学们,我们的征途是星辰大海。就像这段代码里的小火箭,从A点出发,不畏曲折,遍历每一条可能的路径,最终到达C点。
说到底,C++ 精灵库最棒的地方就是:它把专业的编程逻辑,变成了少年能轻松感知、亲手操作的可视化场景。不用再对着冰冷的代码空想,而是看着自己写的程序,让小火箭在屏幕上 “跑” 起来,这种成就感,比单纯背知识点强一百倍!如果你也觉得编程学习太无聊,不妨试试这个精灵库,用玩的心态学编程,说不定你会发现,原来编程可以这么有趣,原来星辰大海的编程梦,离自己这么近。 想看视频效果,网址在这里:https://www.douyin.com/video/7600985547170958627
以下是这个C++程序的所有代码:
#include "sprites.h" //包含C++精灵库 #include <vector> #include <map> using namespace std; Sprite visitor{"res/circle_blue.png"}; //建立角色叫visitor Sprite pathshower; //输出路径A->B-C...的角色 Point A={randint(200,300),randint(200,300)}; Point B={randint(-300,-200),randint(200,300)}; Point C={randint(-300,-200),randint(-300,-200)}; Point D={randint(200,300),randint(-300,-200)}; Point E={0,randint(-350,-330)}; vector<Point> v = {A,B,C,D,E}; vector<Point> path; //存储路径 int anscounter = 0; //存储路径总数 map<Point,string> dict={{A,"A"},{B,"B"},{C,"C"},{D,"D"},{E,"E"}};//节点:名字的 映射 map<Point,bool> visited = {{A,false},{B,false},{C,false},{D,false},{E,false} }; map<Point,vector<Point> > graph = { {A,{B,C,D,E}}, {B,{A,C,D,E}}, {C,{A,B,D,E}}, {D,{A,B,C,E}}, {E,{A,B,C,D}} }; void dfs(Point P){ // 深度优先搜索图 if(P==C){ //到达终点C,则输出路径 anscounter++; string cntstr = to_string(anscounter); string s = "第" + cntstr + "条路径:A"; for(int i=1;i<path.size();i++)s=s+ "->" + dict[path[i]]; pathshower.write(s,30); visitor.wait(3); pathshower.cleartxts(1); //清除最早写的文字 return ; } //到了终点C,则等待3秒种 for(Point &nb:graph[P]) //遍历P的邻接节点 { if(visited[nb]==true)continue; //已经访问过了,则跳过 //可视化到邻居节点 visitor.color(0).speed(1).go(nb).speed(0).wait(0.5); //角色到达邻居节点 visited[nb]=true; //标记此邻居节点已访问 path.push_back(nb); //存入路径 dfs(nb); //从这个节点重新开始dfs visited[nb]=false; //撤销标记 path.pop_back(); //节点弹出 //可视化回退,像时光倒流,红色的血液又流回去了。 visitor.color("cyan").speed(1).go(P).speed(0).wait(0.1); } } int main(){ //主功能块 g_screen->bgcolor("black"); pathshower.hide().color("yellow").speed(0).pu().sety(300); visitor.scale(0.5).speed(0).color("cyan").pu(); for(int i=0;i<v.size();i++) if(i==2)visitor.go(v[i]).mark(dict[v[i]],30,-18,-18); else visitor.go(v[i]).mark(dict[v[i]],30); for(int i=0;i<v.size();i++){ for(int j=i+1;j<v.size();j++) visitor.pu().go(v[i]).dot(10,"blue").pd().go(v[j]); } visitor.dot(10,"blue").pu(); g_screen->savepng("res/graph.png"); g_screen->bgpic("res/graph.png"); visitor.clear(); visited[A]=true; path.push_back(A); visitor.pensize(4).go(A).wait(1).pd(); dfs(A); visitor.hide().done(); //完成了 return 0; //返回0 }
浙公网安备 33010602011771号