快看!他电脑的Terminal上飘过一只兔子🐰!

8,349 阅读3分钟

我正在参加「兔了个兔」创意投稿大赛,详情请看:「兔了个兔」创意投稿大赛

前言

本文介绍如何用C语言在LinuxTerminal上输出一只奔跑的兔子,Mac系统也可以。

作为一名Java程序员,多多少少会一点C语言,那就用C语言编译打印出一只兔子吧,还不是分分钟的事,嗯...还真不是分分钟的事。

废话不多说,先看个效果图。

QQ20230110-122305-HD.gif

什么?这个兔子有点抽象?先凑合着看吧,毕竟是一个符号一个符号打印出来的,光用字符拼出这个小兔子就花了好几个小时,毕竟想象力有限。。。。

实现思路

兔子原型

先找到一只兔子的原型,呐,下面这张图就是兔子的原型,怎么样?和我打印的像不像?嗯......不能说一模一样,只能说毫不相干!😂😂

image.png

符号转化

找到图片后,盯着图片看了大半天,构思兔子的结构,开始用符号把兔子的样子给表现出来。

先准备一个空白文档,按照图片的样子尝试画出来,下面是我画的样子。

image.png

程序准备

C语言在终端Terminal输出动效,需要用到curses模式,curses模式可以在终端内绘制简单的图形用户界面。

静态部分

首先把用符号拼成的兔子的样子在头文件里定义出来。

#define RABBIT_STR1   "                        .'''.                           "
#define RABBIT_STR2   "               .'.   .'      '.                         "
#define RABBIT_STR3   "             .'   `.'         `                         "
#define RABBIT_STR4   "            /     /           `                         "
#define RABBIT_STR5   "           .''```/````''.    '                          "
#define RABBIT_STR6   "        .'               `'.`                           "
#define RABBIT_STR7   "      .'       _           `.                           "
#define RABBIT_STR8   "     '       ((*))          /                           "
#define RABBIT_STR9   "     `                     /  . ''` ` ` '.              "
......省略一部分

动态部分

考虑到要做成动态的效果,一开始想让兔子整体的动起来,一蹦一蹦的,后来实现太麻烦了,就只让腿部部分进行动起来,定义代码如下:

#define RABBIT_LEG11 "                /`    .`........`        /`                 "
#define RABBIT_LEG12 "               `....`         . ` .   /``                   "
#define RABBIT_LEG13 "                              `......`                      "

#define RABBIT_LEG21 "                /`    .`........`        /`                 "
#define RABBIT_LEG22 "               `....`         . ` .   /``                   "
#define RABBIT_LEG23 "                              `......`                      "

......省略一部分

简单起见一共定义了3组动画效果,也就是前腿部分伸长看起来是用力的部分,后腿部分左右移动。

程序实现

实现的过程其实也很简单,首先获取Terminal的宽度,关闭Terminal的回显模式,根据Terminal的宽度一次减少一个,将兔子打印出来。

int main(int argc, char *argv[])
{
    int x;

    initscr();
    signal(SIGINT, SIG_IGN);
    noecho();
    curs_set(0);
    nodelay(stdscr, TRUE);
    leaveok(stdscr, TRUE);
    scrollok(stdscr, FALSE);

    for (x = COLS - 1;; --x)
    {
        add_rabbit(x);
        getch();
        refresh();
        usleep(50000);
    }
    mvcur(0, COLS - 1, LINES - 1, 0);
    endwin();
}

int add_rabbit(int x)
{
    static char *RABBIT[RABBIT_PATTERNS][RABBIT_HIGHT + 1] =
        {这里是头文件里定义的小兔子符号,太多了,展示起来不优雅就先不展示了。};

    if (x < -RABBIT_LENGTH)
        return ERR;

    int y, i;
    y = (x / 14) + LINES - (COLS / 14) - RABBIT_HIGHT;

    for (i = 0; i <= RABBIT_HIGHT; ++i)
    {
        printstr(y + i, x, RABBIT[(RABBIT_LENGTH + x) % RABBIT_PATTERNS][i]);
    }
    return OK;
}

程序说明

initscr函数是开启curses模式,获取指向stdscr结构的指针。

endwin函数是关闭curses模式,运行结束后回到命令行交互界面。

signal(SIGINT, SIG_IGN)忽略中断信息,让小兔子跑完,不受外界干扰。

curs_set设置光标不可见。

getch为非阻塞等待, 即使没有输入程序也能继续执行。

add_rabbit函数,就是把头文件里定义好的小兔子的符号给输出到Terminal里。

程序里的for循环,是在Terminal里从左到右绘制小兔子图形,每次一循环刷新下小兔子的位置。

程序运行

编译一下,运行看看。

/usr/bin/gcc -fdiagnostics-color=always -g rabbit.c -o rabbit -l curses

编译成功后会生成一个rabbit可执行文件。

运行文件,直接在Terminal./rabbit就可以执行了,如果把这个文件放到/usr/bin目录下,可以直接在Terminal里输入rabbit也能运行。

总结

一个在Terminal中输出一个蹦蹦跳跳的兔子,就这样实现了,不过由于实现的有些抽象,细节还有待打磨。

如果你觉得本文有趣就给作者点个赞吧。