优秀代码后默默无闻的库 柔情只为你懂 2022-12-15 12:49 66阅读 0赞 ### 优秀代码后默默无闻的库 ### * 一、 函数库 * * 1. 简介 * 2. 优点 * 3. 安装目录 * 二、 curses库 * * 1. curses安装 * 2. 主要函数与功能 * 3. 函数实例 * 3. 体验远古光标论坛(BBS) * 三、 Linux下的贪吃蛇(C语言) * * 1.创建mysnake1.0.c * 2. 编译 * 3. 游玩贪吃蛇 * 4. 分析部分代码 * 四、 总结 * 五、 参考资料 > 摘要:库函数(Library function)是把函数放到库里,供别人使用的一种方式。方法是把一些常用到的函数编完放到一个文件里,供不同的人进行调用。 > 关键字:**Linux**,**库函数**,**curses** # 一、 函数库 # ## 1. 简介 ## 库就是指始终可以被多个软件项目重复使用的代码集。库是由系统建立的具有一定功能的函数的集合。库中存放函数的名称和对应的目标代码,以及连接过程中所需的重定位信息。用户也可以根据自己的需要建立自己的用户函数库。 ## 2. 优点 ## ·可以简化编程,实现代码重复使用,进而减少应用程序的大小 ·可以直接使用比较稳定的代码 ## 3. 安装目录 ## Linux的库一般在`/lib`或`usr/lib`目录下。它主要存放系统的链接库文件,没有该目录则系统无法正常运行。 <table> <thead> <tr> <th>库名称</th> <th>说明</th> </tr> </thead> <tbody> <tr> <td>lib.so</td> <td>标准的C库</td> </tr> <tr> <td>libdl.so</td> <td>可以使用库的源代码而无需静态编译的库</td> </tr> <tr> <td>libvga.so</td> <td>Linux的VGA和SVGA图形库</td> </tr> <tr> <td>libpthread.so</td> <td>Linux多线程库</td> </tr> <tr> <td>…</td> <td>…</td> </tr> </tbody> </table> # 二、 curses库 # > curses是一个在Linux/Unix下广泛应用的图形函数库,作用是可以在终端内绘制简单的图形用户界面。[百度百科][Link 1] ## 1. curses安装 ## Ubuntu下安装方法: > sudo apt-get install libncurses5-dev 这里我们安装完成之后可以去在`usr/lib`目录下找到`libncurses.so`或`libncurses.a`看是否安装成功。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center] 或者输入命令: > whereis curses ![在这里插入图片描述][20201016215852739.png_pic_center] 可以看出我们成功安装curses库。 ## 2. 主要函数与功能 ## <table> <thead> <tr> <th>函数</th> <th>功能</th> </tr> </thead> <tbody> <tr> <td>initscr()</td> <td>初始化curses库和ttty(在开始curses编程之前,必须使用initscr()这个函数来开启curses模式)</td> </tr> <tr> <td>endwin()</td> <td>关闭curses并重置tty(结束curses编程时,最后调用的一个函数)</td> </tr> <tr> <td>move(y,x)</td> <td>将游标移动至 x,y 的位置</td> </tr> <tr> <td>getyx(win,y,x)</td> <td>得到目前游标的位置(请注意!是 y,x 而不是&y,&x)</td> </tr> <tr> <td>mvaddstr(y,x,str)</td> <td>在(x,y) 上显示一串字串。相当于呼叫move(y,x);addstr(str)</td> </tr> <tr> <td>printw(format,str)</td> <td>类似 printf() ,以一定的格式输出至萤幕</td> </tr> <tr> <td>…</td> <td>…</td> </tr> </tbody> </table> 表2.2curses主要函数与功能-[百度百科][Link 1] ## 3. 函数实例 ## 1. 包含头文件:curses.h 2. 编译时应加上链接语句-lcurses, 如:gcc temp.c -o temp -lcurses 3. 实例 [curses实例来源-博主:qvb3d][curses_-_qvb3d] ①创建cur.c > vim cur.c cur.c代码如下: #include <stdio.h> #include <unistd.h> #include <errno.h> #include <stdlib.h> #include <curses.h> int main(int argc,char *argv[]) { WINDOW *win; if((initscr())==NULL) { perror("initscr"); exit(EXIT_FAILURE); } start_color(); init_pair(COLOR_RED,COLOR_WHITE,COLOR_RED); init_pair(COLOR_BLUE,COLOR_WHITE,COLOR_BLUE); // name , forecolor,bgcolor init_pair(COLOR_GREEN,COLOR_BLACK,COLOR_GREEN); init_pair(COLOR_MAGENTA,COLOR_WHITE,COLOR_MAGENTA); init_pair(COLOR_CYAN,COLOR_WHITE,COLOR_CYAN); init_pair(COLOR_YELLOW,COLOR_BLACK,COLOR_YELLOW); init_pair(COLOR_WHITE,COLOR_BLACK,COLOR_WHITE); refresh(); curs_set(0); noecho(); clear(); win=newwin(10,110,10,10); wborder(win,0,0,0,0,0,0,0,0); wbkgd(win,' '|COLOR_PAIR(COLOR_BLUE)); mvwaddstr(win,2,2,"This test Blue Window "); touchwin(win); wrefresh(win); sleep(3); wbkgd(win,' '|COLOR_PAIR(COLOR_YELLOW)); mvwaddstr(win,2,2,"This test Yellow Window "); wrefresh(win); sleep(3); wbkgd(win,' '|COLOR_PAIR(COLOR_RED)); mvwaddstr(win,2,2,"This test Red Window "); wrefresh(win); sleep(3); wbkgd(win,' '|COLOR_PAIR(COLOR_GREEN)); mvwaddstr(win,2,2,"This test Green Window "); wrefresh(win); sleep(3); wbkgd(win,' '|COLOR_PAIR(COLOR_MAGENTA)); mvwaddstr(win,2,2,"This test Magenta Window"); wrefresh(win); sleep(3); wbkgd(win,' '|COLOR_PAIR(COLOR_CYAN)); mvwaddstr(win,2,2,"This test Cyan Window "); wrefresh(win); sleep(3); wbkgd(win,' '|COLOR_PAIR(COLOR_WHITE)); mvwaddstr(win,2,2,"This test White Window "); wrefresh(win); sleep(3); delwin(win); printw("This is printw\n"); refresh(); sleep(3); endwin(); } 编译: > gcc cur.c -o cur -lcurses 运行可执行文件: > ./cur *该程序运行一段时间(30s)后会自动关闭*。 ![在这里插入图片描述][20201016220630972.gif_pic_center] 可以看出此次curses安装成功且可以正常编译使用。 ## 3. 体验远古光标论坛(BBS) ## 环境:Win10 ①“控制面板”–>“程序”—>“启用或关闭Windows功能” ![在这里插入图片描述][20201016223400829.png_pic_center] ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 1] ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 2] ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 3] ②启用 “telnet client” 和"适用于Linux的Windows子系统" ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 4] > **注意:点击确认后win10系统会进行配置工具,配置完成后需要重启电脑才可以正常使用该服务。** ③打开一个cmd命令行窗口 > win+R键打开运行,并点击确定 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 5] ④命令行输入: > telnet bbs.newsmth.net ⑤主界面 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 6] 输入:`guest`就可以以游客身份在水木社区(远古BBS)中体验当时键盘光标的论坛了。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 7] 可以看到远古时代的电子论坛是由简单的字符与光标构成,但社交功能完善,具有公式通知,聊天,发帖等功能。 # 三、 Linux下的贪吃蛇(C语言) # > 贪食蛇是大多数人的童年,对大多数人也有着不一样的情感。所以此次将在Linux系统下进行gcc编译实现贪吃蛇游戏以来提高大家对Linux系统中的curses(光标库)的认识和对Linux学习的兴趣。 > 此游戏代码来源:[贪吃蛇][Link 2] ## 1.创建mysnake1.0.c ## > vim mysnake1.0.c ![在这里插入图片描述][20201016233613846.png_pic_center] mysnake1.0.c代码如下: //mysnake1.0.c //编译命令:cc mysnake1.0.c -lcurses -o mysnake1.0 //用方向键控制蛇的方向 #include <stdio.h> #include <stdlib.h> #include <curses.h> #include <signal.h> #include <sys/time.h> #define NUM 60 struct direct //用来表示方向的 { int cx; int cy; }; typedef struct node //链表的结点 { int cx; int cy; struct node *back; struct node *next; }node; void initGame(); //初始化游戏 int setTicker(int); //设置计时器 void show(); //显示整个画面 void showInformation(); //显示游戏信息(前两行) void showSnake(); //显示蛇的身体 void getOrder(); //从键盘中获取命令 void over(int i); //完成游戏结束后的提示信息 void creatLink(); //(带头尾结点)双向链表以及它的操作 void insertNode(int x, int y); void deleteNode(); void deleteLink(); int ch; //输入的命令 int hour, minute, second; //时分秒 int length, tTime, level; //(蛇的)长度,计时器,(游戏)等级 struct direct dir, food; //蛇的前进方向,食物的位置 node *head, *tail; //链表的头尾结点 int main() { initscr(); initGame(); signal(SIGALRM, show); getOrder(); endwin(); return 0; } void initGame() { cbreak(); //把终端的CBREAK模式打开 noecho(); //关闭回显 curs_set(0); //把光标置为不可见 keypad(stdscr, true); //使用用户终端的键盘上的小键盘 srand(time(0)); //设置随机数种子 //初始化各项数据 hour = minute = second = tTime = 0; length = 1; dir.cx = 1; dir.cy = 0; ch = 'A'; food.cx = rand() % COLS; food.cy = rand() % (LINES-2) + 2; creatLink(); setTicker(20); } //设置计时器(这个函数是书本上的例子,有改动) int setTicker(int n_msecs) { struct itimerval new_timeset; long n_sec, n_usecs; n_sec = n_msecs / 1000 ; n_usecs = ( n_msecs % 1000 ) * 1000L ; new_timeset.it_interval.tv_sec = n_sec; new_timeset.it_interval.tv_usec = n_usecs; n_msecs = 1; n_sec = n_msecs / 1000 ; n_usecs = ( n_msecs % 1000 ) * 1000L ; new_timeset.it_value.tv_sec = n_sec ; new_timeset.it_value.tv_usec = n_usecs ; return setitimer(ITIMER_REAL, &new_timeset, NULL); } void showInformation() { tTime++; if(tTime >= 1000000) // tTime = 0; if(1 != tTime % 50) return; move(0, 3); //显示时间 printw("time: %d:%d:%d %c", hour, minute, second); second++; if(second > NUM) { second = 0; minute++; } if(minute > NUM) { minute = 0; hour++; } //显示长度,等级 move(1, 0); int i; for(i=0;i<COLS;i++) addstr("-"); move(0, COLS/2-5); printw("length: %d", length); move(0, COLS-10); level = length / 3 + 1; printw("level: %d", level); } //蛇的表示是用一个带头尾结点的双向链表来表示的, //蛇的每一次前进,都是在链表的头部增加一个节点,在尾部删除一个节点 //如果蛇吃了一个食物,那就不用删除节点了 void showSnake() { if(1 != tTime % (30-level)) return; //判断蛇的长度有没有改变 bool lenChange = false; //显示食物 move(food.cy, food.cx); printw("@"); //如果蛇碰到墙,则游戏结束 if((COLS-1==head->next->cx && 1==dir.cx) || (0==head->next->cx && -1==dir.cx) || (LINES-1==head->next->cy && 1==dir.cy) || (2==head->next->cy && -1==dir.cy)) { over(1); return; } //如果蛇头砬到自己的身体,则游戏结束 if('*' == mvinch(head->next->cy+dir.cy, head->next->cx+dir.cx) ) { over(2); return; } insertNode(head->next->cx+dir.cx, head->next->cy+dir.cy); //蛇吃了一个“食物” if(head->next->cx==food.cx && head->next->cy==food.cy) { lenChange = true; length++; //恭喜你,通关了 if(length >= 50) { over(3); return; } //重新设置食物的位置 food.cx = rand() % COLS; food.cy = rand() % (LINES-2) + 2; } if(!lenChange) { move(tail->back->cy, tail->back->cx); printw(" "); deleteNode(); } move(head->next->cy, head->next->cx); printw("*"); } void show() { signal(SIGALRM, show); //设置中断信号 showInformation(); showSnake(); refresh(); //刷新真实屏幕 } void getOrder() { //建立一个死循环,来读取来自键盘的命令 while(1) { ch = getch(); if(KEY_LEFT == ch) { dir.cx = -1; dir.cy = 0; } else if(KEY_UP == ch) { dir.cx = 0; dir.cy = -1; } else if(KEY_RIGHT == ch) { dir.cx = 1; dir.cy = 0; } else if(KEY_DOWN == ch) { dir.cx = 0; dir.cy = 1; } setTicker(20); } } void over(int i) { //显示结束原因 move(0, 0); int j; for(j=0;j<COLS;j++) addstr(" "); move(0, 2); if(1 == i) addstr("Crash the wall. Game over"); else if(2 == i) addstr("Crash itself. Game over"); else if(3 == i) addstr("Mission Complete"); setTicker(0); //关闭计时器 deleteLink(); //释放链表的空间 } //创建一个双向链表 void creatLink() { node *temp = (node *)malloc( sizeof(node) ); head = (node *)malloc( sizeof(node) ); tail = (node *)malloc( sizeof(node) ); temp->cx = 5; temp->cy = 10; head->back = tail->next = NULL; head->next = temp; temp->next = tail; tail->back = temp; temp->back = head; } //在链表的头部(非头结点)插入一个结点 void insertNode(int x, int y) { node *temp = (node *)malloc( sizeof(node) ); temp->cx = x; temp->cy = y; temp->next = head->next; head->next = temp; temp->back = head; temp->next->back = temp; } //删除链表的(非尾结点的)最后一个结点 void deleteNode() { node *temp = tail->back; node *bTemp = temp->back; bTemp->next = tail; tail->back = bTemp; temp->next = temp->back = NULL; free(temp); temp = NULL; } //删除整个链表 void deleteLink() { while(head->next != tail) deleteNode(); head->next = tail->back = NULL; free(head); free(tail); } ## 2. 编译 ## > cc mysnake1.0.c -lcurses -o mysnake1.0 ![在这里插入图片描述][2020101623381780.png_pic_center] ![在这里插入图片描述][20201016233546198.png_pic_center] > **知识拓展**:如果讨论范围在Unix和Linux之间,那么cc和gcc不是同一个东西。cc来自于Unix的c语言编译器,是 c compiler 的缩写。gcc来自Linux世界,是GNU compiler collection 的缩写,注意这是一个编译器集合,不仅仅是c或c++。 > 其次, 如果讨论范围仅限于Linux,我们可以认为它们是一样的,在Linux下调用cc时,其实际上并不指向unix的cc编译器,而是指向了gcc,也就是说cc是gcc的一个链接(快捷方式)。[Linux 下 的 cc 和 gcc—博主周银辉][Linux _ _ cc _ gcc] ## 3. 游玩贪吃蛇 ## > ./mysnake1.0 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 8] ## 4. 分析部分代码 ## void initGame() { cbreak(); //把终端的CBREAK模式打开 noecho(); //关闭回显 curs_set(0); //把光标置为不可见 keypad(stdscr, true); //使用用户终端的键盘上的小键盘 srand(time(0)); //设置随机数种子 //初始化各项数据 hour = minute = second = tTime = 0; length = 1; dir.cx = 1; dir.cy = 0; ch = 'A'; food.cx = rand() % COLS; food.cy = rand() % (LINES-2) + 2; creatLink(); setTicker(20); } curses的链接与使用: 1. 包含头文件:curses.h 2. 编译时应加上链接语句-lcurses, 如:gcc temp.c -o temp -lcurses # 四、 总结 # 通过此次学习,了解了软件中函数库的重要性,了解到库的优点:1.可以简化编程,实现代码重复使用,进而减少应用程序的大小2.可以直接使用比较稳定的代码;通过curses库的熟悉与调用,了解了curses库可以将字符绘制出简单的图形用户界面或者在终端游戏上大显身手。 # 五、 参考资料 # 1.[curses-百度百科][Link 1] 2.[Curses 实例][curses_-_qvb3d] 3.[Linux 下 的 cc 和 gcc][Linux _ _ cc _ gcc] 4.[Linux 环境下C语言编译实现贪吃蛇游戏][Link 2] > 本博客仅作为学习经验分享,如有侵权,请联系我。谢谢大家阅读。 [Link 1]: https://baike.baidu.com/item/curses/1630775?fr=aladdin#3 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center]: /images/20221123/aecb1ab7ceac4f72ab8e305751cb5061.png [20201016215852739.png_pic_center]: /images/20221123/d7c1705d829b4e00bd64cac96e13c084.png [curses_-_qvb3d]: https://blog.csdn.net/qvb3d/article/details/84180634?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160285572419195188336590%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=160285572419195188336590&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v28-1-84180634.first_rank_ecpm_v3_pc_rank_v2&utm_term=curses%E5%AE%9E%E4%BE%8B&spm=1018.2118.3001.4187 [20201016220630972.gif_pic_center]: /images/20221123/cf79675fd71846209d875add2557611e.png [20201016223400829.png_pic_center]: /images/20221123/2d0b42d5df6446dc97a978a71c2dd4b8.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 1]: /images/20221123/cbce2dfed3f6448698c2ed4732da6e2c.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 2]: /images/20221123/77565addf5ff4d9a9873cbab727dcebd.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 3]: /images/20221123/805618c6cbb1437e8621da826e9368e4.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 4]: /images/20221123/31e7aacb0d5142e49d26aac61fbbce0b.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 5]: /images/20221123/ce64aef5df8a433fad378d40572e32ac.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 6]: /images/20221123/6d97dea9f1084e86a09fe3200d20c2a3.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 7]: /images/20221123/11e953055e354380978ad1898b203074.png [Link 2]: http://www.linuxidc.com/Linux/2011-08/41375.htm [20201016233613846.png_pic_center]: /images/20221123/0d16dd9249314ffdbc3481bb1db08df5.png [2020101623381780.png_pic_center]: /images/20221123/bb8c5e25ed3240d3a4ad7bc59bd32540.png [20201016233546198.png_pic_center]: /images/20221123/caebfdd2fb2746969d07f0926cc1b40d.png [Linux _ _ cc _ gcc]: https://www.cnblogs.com/zhouyinhui/archive/2010/02/01/1661078.html [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MjY0ODA4_size_16_color_FFFFFF_t_70_pic_center 8]: /images/20221123/20a15d24d6e341d6a43ae68b038efde7.png
还没有评论,来说两句吧...