近看到大神在Linux下写的贪吃蛇代码,用到了curses图形库,可能很多人都没有用过,分享出来给大家。
在ubuntu下安装curses图形库命令
- sudo apt-get install libncurses5-dev
双buff是一个非常优秀的机制,之前写贪吃蛇的时候,如果不使用双buff屏幕跳动会很剧烈,使用了双buff后体验就非常好。
我们使用curses图形库也是一样,如果没有调用refresh()函数之前,显示的屏幕是不会进行更新的。
比如下面这段代码
- #include <unistd.h>
- #include <stdlib.h>
- #include <curses.h>
- int main()
- {
- initscr();
-
- move(5, 15);
- addstr("Hello World");
- refresh();
- sleep(2);
- endwin();
- exit(EXIT_SUCCESS);
- }
使用下面的命令编译并运行
- gcc -o t screen1.c -lncurses && ./t
首先初始化一个屏幕,然后移动到屏幕的 5,15位置,在输出字符串 Hello World。之后休眠 2秒后,程序退出。
使用curses写贪吃蛇代码
- //sudo apt-get install libncurses5-dev
- //gcc -o t tanchishe.c -lncurses && ./t
- #include <curses.h> // Linux 下的图形库
- #include <unistd.h> // usleep()
- #include <stdlib.h> // rand()
- #include <time.h> // time()
- #define W 40
- #define H 24
- int m[W * H], q[W * H], p = H / 2 * W + (W / 2), a, h = 0, t = 0, d = 1, i;
- int main(void) {
- initscr(); noecho(); keypad(stdscr, 1); nodelay(stdscr, 1); curs_set(0);
- srand(time(NULL));
- for (i = 0; i < W * H; i++)
- m[i] = !(i / W % (H - 1) && i % W % (W - 1));
- m[q[t = (t + 1) % (W * H)] = p] = 1;
- do { a = rand() % (W * H); } while (m[a]);
- while ((i = getch()) != 27) {
- if (i == KEY_UP && d != W) d = -W;
- else if (i == KEY_DOWN && d != -W) d = W;
- else if (i == KEY_LEFT && d != 1) d = -1;
- else if (i == KEY_RIGHT && d != -1) d = 1;
- if (m[p += d]) break;
- m[q[t = (t + 1) % (W * H)] = p] = 1;
- if (p == a) do { a = rand() % (W * H); } while (m[a]);
- else m[q[h = (h + 1) % (W * H)]] = 0;
- for (i = 0; i < W * H; i++)
- mvaddstr(i / W, (i % W) * 2, m[i] ? "[]" : " ");
- mvaddstr(a / W, (a % W) * 2, "()");
- refresh();
- usleep(100000);
- }
- while (getch() == ERR);
- endwin();
- }
程序运行
简单解释下
- for (i = 0; i < W * H; i++)
- mvaddstr(i / W, (i % W) * 2, m[i] ? "[]" : " ");
构建边框和蛇身的代码,边框是用 [] 构建的,用这个字符从视觉上看会比较舒服。
- mvaddstr(a / W, (a % W) * 2, "()");
随机生成的食物,之前已经用时间srand(time(NULL));作为种子设置了随机数。
- if (m[p += d]) break;
碰撞检测
- if (p == a) do { a = rand() % (W * H); } while (m[a]);
- else m[q[h = (h + 1) % (W * H)]] = 0;
如果碰撞到了食物,就增加蛇长度,m[]里面同时保存蛇的数据和边框的数据,并且蛇移动的时候,需要把后面的数值设置为0。
- p = H / 2 * W + (W / 2)
蛇的初始位置
自己修改的代码,可以实现穿墙效果
- //sudo apt-get install libncurses5-dev
- //gcc -o t tanchishe.c -lncurses && ./t
- #include <curses.h> // Linux 下的图形库
- #include <unistd.h> // usleep()
- #include <stdlib.h> // rand()
- #include <time.h> // time()
- #define W 40
- #define H 24
- int m[W * H], q[W * H], p = H / 2 * W + (W / 2), a, h = 0, t = 0, d = 1, i,j=3;
- int main(void) {
- initscr(); noecho(); keypad(stdscr, 1); nodelay(stdscr, 1); curs_set(0);
- srand(time(NULL));
- for (i = 0; i < W * H; i++) m[i] = !(i / W % (H - 1) && i % W % (W - 1));
- m[q[t = (t + 1) % (W * H)] = p] = 1;
- do { a = rand() % (W * H); } while (m[a]);
- while ((i = getch()) != 27) {
- if (i == KEY_UP && d != W) {d = -W;j=0;}
- else if (i == KEY_DOWN && d != -W) {d = W;j=1;}
- else if (i == KEY_LEFT && d != 1) {d = -1;j=2;}
- else if (i == KEY_RIGHT && d != -1) {d = 1;j=3;}
- if (m[p += d]) {
- switch(j){
- case 0:p = p+(H-2)*W; break;
- case 1:p = p-(H-2)*W; break;
- case 2:p = p+W-2; break;
- case 3:p = p-W+2; break;
- default: p = H / 2 * W + (W / 2); break;
- }
- };
- m[q[t = (t + 1) % (W * H)] = p] = 1;
- if (p == a) do { a = rand() % (W * H); } while (m[a]);
- else m[q[h = (h + 1) % (W * H)]] = 0;
- for (i = 0; i < W * H; i++){
- mvaddstr(i / W, (i % W) * 2, m[i] ? "[]" : " ");
- }
- mvaddstr(a / W, (a % W) * 2, "()");
- refresh();
- usleep(100000);
- }
- while (getch() == ERR);
- endwin();
- }
运行如下:
代码原文:
https://www.zhihu.com/question/360814879/answer/1013986215