linux上c语言贪吃蛇,在linux下用C语言编写贪吃蛇小游戏-Go语言中文社区

利用链表和结构体来编写贪吃蛇小游戏,这边还会用点线程,分别有以下模块:

1、地图规划

2、蛇身体的初始化

3、蛇的方向移动

4、食物的初始化和随机出现

5、蛇撞墙和咬自己的尾巴

地图规划

我们在设计地图的时候,需要用到ncurses,头文件 #include

ncurses(new curses)是一个程序库,它提供了API,可以允许程序员编写独立于终端的基于文本的用户界面。它是一个虚拟终端中的“类GUI”应用软件工具箱。它还优化了屏幕刷新方法,以减少使用远程shell时遇到的延迟。我们需要在虚拟机中装以下ncurses库

sudo apt-get install libncurses5-dev

sudo apt-get install ncurses-doc//这是ncurses的文件内容 可以查看ncurse的函数说明

man endwin//查看endwin函数的说明

使用ncurses的主要语句:

initscr(); //使用ncurses首先要初始化一下

printw("hello");//输出语句

getch();//等待用户输入

endwin();//结束并退出ncurses

move(y,x); // 将光标移动至(x,y)处。

refresh() ; //经过refresh()函数刷新之后才能够显示到屏幕上。

设计一个20x20的地图,我们可以使用两个for循环输出我们的行和列

void gamepic(){ //地图规划

int col;//lie

int row;//行

for (row = 0; row < 20; row++) {

if (row == 0) {

for (col = 0; col < 20; col++) {

printw("--");

}

}

printw("n");

for (col = 0; col <= 20; col++) {

if (col == 0 || col == 20) {

printw("|");

} else{

printw(" ");

}

if (row == 19) {

printw("n");

for (col = 0; col < 20; col++) {

printw("--");

}

}

}

}

d85f34874d7728a8915422e9e8f7ed56.png

2、蛇身体的初始化

这边对蛇身体的构造,我们用链表和结构体来完成身体的构造,结构体内包含行和列、下一个节点指针。通过坐标的形式显示我们蛇的身子

struct Snake {

int row;

int col;

struct Snake *next;

};

struct Snake *head = NULL;

struct Snake *tail = NULL; //这时我们将链表的头结点和尾指针设定为全局变量

void initSnake() { //蛇身体的初始化

struct Snake *p;

while (head != NULL) {

p = head;

head = head->next;

free(p);

}

head = (struct Snake *)malloc(sizeof(struct Snake));

head->row = 2;

head->col = 2;

head->next = NULL;

tail = head;

addNode(); //添加蛇的身子

addNode();

}

void addNode(){

strcut Snake *new=(struct Snake *)malloc(sizeof(struct Snake));

new->next=NULL;

tail->next=new; //添加节点

tail=new;

}

链表创建完毕,现在来显示蛇的身体,这时我们可以通过一个指针对链表进行遍历,如果此时指针所指的行和列符合地图上的行和列,显示蛇的身子。

int Snake_body(int i, int j) { //对蛇的身体链表进行遍历 跟地图的行和列比较,相同返回1,不同返回0

struct Snake *p;

p = head;

while (p != NULL) {

if (p->row == i && p->col == j) {

return 1;

}

p = p->next;

}

return 0;

}

//对地图规划的函数进行修改

for (col = 0; col <= 20; col++) {

if (col == 0 || col == 20) {

printw("|");

} else if (Snake_body(row, col)) { //显示蛇的身体

printw("[]");

} else {

printw(" ");

}

}

4e3090cd1456a9ef9cfd7769573cdd3a.png

3、蛇方向的移动

那么蛇的方向移动是怎么回事呢,假如我们向右移动,就是将我们的链表在右边添加一个节点,然后将最左边的节点删除,再通过更新我们的地图,来达到移动的效果。所以我们要写一个删除节点的函数

void deleteNode() {

struct Snake *p;

p = head;

head = head->next; //将头结点进行移动

free(p);

}

void movesnake() { //蛇身子的移动

addNode();

deleteNode();

}

716240eeda29ee41e4538e7232831865.png

那么如何让蛇一直动起来呢,这时候我们可以利用ncurses的refresh函数,它有刷新屏幕的功能

void refreshJieMian() {

while (1) {

movesnake();

gamepic();

refresh();

usleep(100000); //延迟1ms

}

}

接下来我们要实现通过按键来实现蛇方向的移动,在ncurese中有可以获得上下左右键的值

keypad(stdscr, 1); //将这句话加入initNcurses函数中,意思是从键盘获取上下左右的值

int dir;//设置变量dir为全局变量

#define UP 1

#define DOWN -1

#define LEFT 2

#define RIGHT -2

void turn(int direction) {

if (abs(dir) != abs(direction)) { //以绝对值的方式让蛇单方向行走

dir = direction;

}

}

void changeDir() { //从键盘中获取上下左右的信息

while (1) {

key = getch();

switch (key) {

case KEY_DOWN:

turn(DOWN);

break;

case KEY_UP:

turn(UP);

break;

case KEY_LEFT:

turn(LEFT);

break;

case KEY_RIGHT:

turn(RIGHT);

break;

}

}

}

switch (dir) { //上下左右的移动,将这段加入movesnake函数中

case UP: //上

new->row = tail->row - 1;

new->col = tail->col;

break;

case DOWN: //下

new->row = tail->row + 1;

new->col = tail->col;

break;

case LEFT: //左

new->row = tail->row;

new->col = tail->col - 1;

break;

case RIGHT: //右

new->row = tail->row;

new->col = tail->col + 1;

break;

}

4、食物的初始化和随机出现

struct Snake food; //用蛇的结构体来定义一个食物

void initfood() {

int x = rand() % 20; //随机取值,因为地图是20x20的,要在这范围中出现,对20求余数

int y = rand() % 20;

food.row = x;

food.col = y;

}

int Snake_food(int i, int j) { //跟身子的显示道理一样

if (food.row == i && food.col == j) {

return 1;

}

return 0;

}

//对将食物的显示加入地图规划函数中

for (col = 0; col <= 20; col++) {

if (col == 0 || col == 20) {

printw("|");

} else if (Snake_body(row, col)) {

printw("[]");

} else if (Snake_food(row, col)) {

printw("##");

} else {

printw(" ");

}

}

5、蛇撞墙和自杀

对链表的尾指针的值进行判断,超过地图的范围就将它初始化

int ifsnakedie() {

struct Snake *p;

p = head;

if (tail->row == -1 || tail->row == 20 || tail->col == 0 || //撞墙

tail->col == 20) {

return 1;

}

while (p->next != NULL) {

if (p->row == tail->row && p->col == tail->col) { //咬到自己的尾巴

return 1;

}

p = p->next;

}

return 0;

}

//修改移动函数

void movesnake() {

addNode();

if (Snake_food(tail->row, tail->col)) { //if判断的作用,如果吃到食物就让身子边长,加一个节点,并重新显示食物的位置。没有吃到则不变

initfood();

} else {

deleteNode();

}

if (ifsnakedie()) {

initSnake();

}

}

贪吃蛇的具体功能函数已经完成,在最后我们可以将入线程来完成最后的步骤

//主函数 线程的头文件一定要加 #include

void main() {

pthread_t t1;

pthread_t t2;

initNcurses();

initSnake();

gamepic();

pthread_create(&t1, NULL, refreshJieMian, NULL); //在refreshJieMian函数名前记得要加*

pthread_create(&t2, NULL, changeDir, NULL); //在changeDir函数名前记得要加*

while (1) ;

getch();

endwin();

}

ae82d74e6058ae6e04e2601620e1198d.png

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值