c语言void move,C语言循环链表实现贪吃蛇游戏

本文实例为大家分享了C语言表实现贪吃蛇游戏的具体代码,供大家参考,具体内容如下

总体思想

利用循环链表将一条蛇的坐标进行存储,然后利用gotoxy()函数(可以将光标定位到指定的位置),此时根据蛇的坐标进行输出“@”,输出多几个既可以产生一条蛇。通过遍历循环链表进行蛇的移动,对循环链表的插入元素,产生蛇变长的效果。下面为各功能实现的函数

1.贪吃蛇地图函数map()

2.蛇的移动move(),up(),left()等函数

3.产生食物food()和吃到食物eat_food()

4.蛇吃到食物时产生的变长效果snake_link()函数

5.判断蛇的死亡,分别为撞墙hit_wall()和自杀suicide()

1.贪吃蛇地图函数map()

游戏地图采用的是应该封闭的区域,采用一个数组a[25][50],将此数组初始化为0,将游戏墙的边缘赋值为1,当数组为0,输出" ",数组为1,输出“#”,产生一个地图。

代码如下:

void map() //创建蛇的地图

{

int a[25][50] = {0};

int i,j;

for(i = 0; i < 50; i++)

{

a[0][i] = 1;

a[24][i] =1;

}

for(i = 0; i < 25; i++)

{

a[i][0] = 1;

a[i][49] =1;

}

for(i = 0; i < 25; i++)

for(j = 0; j < 50; j++)

{

if(j%50 == 0)

printf("\n");

if(a[i][j] == 0)

{

printf(" ");

}

else

{

printf("#");

}

}

}

2.蛇的移动move(),up(),left()等函数

move()函数主要对蛇的上下左右进行更改在此采用switch函数进行解决(下面代码中ch为全局变量)

代码如下

void move(struct snake *p) //蛇的移动函数

{

while(1)

{

ch = getch();

switch(ch)

{

case 'W':p = up(p);break;

case 'A':p = left(p);break;

case 'D':p = right(p);break;

case 'S':p = down(p);break;

}

}

}

让蛇动起来的即我们主要对蛇的坐标进行更改,此时蛇头移动一次我们就利用gotoxy()函数进行输出“@”,然后在蛇尾输出“ ”,循环往复就可以产生蛇移动的效果,蛇的上下左右则只需在移动一个方向的时候对单一的坐标x或y进行更改,然后对更改的坐标保存进循环链表即可。移动函数则主要有up(),left()等,因为做法差不多,在此只对up()函数进行展示

代码如下

struct snake *up(struct snake *p) //向上移动

{

int x;

int y;

x = p->pre->x; //将蛇头坐标赋值给x,y

y = p->pre->y;

while(p) //对循环链表的遍历,即蛇的遍历

{

Sleep(SNAKE_SPEED); //蛇移动的速度

y--; //向上移动则只需将纵坐标进行减,就可以实现蛇向上移动的效果

gotoxy(p->x,p->y); //定位到蛇尾,输出“ ”即蛇尾消失

printf(" ");

gotoxy(x, y); //定位到蛇头输出,"@",结合上面的蛇尾消失又进行蛇头打印,产生蛇移动的效果

printf("@");

suicide(p,x,y); //判断蛇头是否撞到蛇身

p = p->next; //将蛇头的坐标变为下一个

p->pre->x = x; //此时将前一个蛇头变成蛇尾,通过不断的遍历产生不断移动的效果

p->pre->y = y;

food(); //产生食物

eat_food(p,x,y); //判断是否吃到食物

hit_wall(y); //判断是否撞墙

if(kbhit()) break; //判断是否有按键输入,有就进行蛇移动方向的改变

}

return p;

}

3.产生食物food()和吃到食物eat_food()

食物和吃到食物,产生食物则采用了产生随机数,产生一个食物的x,y坐标分别存放在全局变量food_xy[2]数组里面,最后利用gotoxy(food_xy[0],food_xy[1])随机产生食物

代码如下

void food() //产生食物

{

int i;

if(!flag) //根据flag的值来判断地图上是否有食物

{

srand( (unsigned)time( NULL ) );

for( i = 0; i < 2; i++ ) //对food_(x,y)来随机赋值

{

food_xy[i] = rand()%24+2;

while(food_xy[0] == 1 || food_xy[0] == 25) //这两个while为了防止食物

food_xy[0] = rand()%24+2; //的坐标与地图的边缘重叠

while(food_xy[1] >= 49 || food_xy[1] == 1)

food_xy[1] =rand()%24+2;

}

gotoxy(food_xy[0],food_xy[1]); //打印食物

printf("*");

flag = 1;

}

}

吃到食物eat_food(),则我们只需判断蛇头是否和食物的坐标重叠,若重叠则表明蛇吃到了食物

代码如下

void eat_food(struct snake *p,int x, int y) //蛇吃到食物,即主要是对蛇头的x,y坐标和

{ //food_xy的坐标进行匹配对比,若相同即调

if(x == food_xy[0] && y == food_xy[1]) //snake_link函数即可

{

p = snake_link(p);

flag = 0; //表明食物被吃,准备重新产生食物

printSnake(p);

gotoxy(8,0);

score = score + 1; //得分

printf("%d",score);

}

}

4.蛇吃到食物时产生的变长效果snake_link()函数

蛇的变长,当蛇吃到食物的时候,此时我们将食物的坐标变成蛇头,然后进行重新的打印蛇,即可以有蛇变成的效果产生,实质为对循环链表进行元素的插入。

5faef93d6e34c0b4eafc94f97bdf13dc.png

即通过这样将食物的坐标插进去循环链表,达到蛇变成的效果

代码如下

struct snake *snake_link(struct snake *p) //蛇的连接

{

struct snake *q;

q = (struct snake *)malloc(sizeof(struct snake)); //即主要是实现了对循环链表的插入元素,再

q->x = food_xy[0]; //进行打印蛇,即可有吃到食物蛇变长的结果

q->y = food_xy[1];

q->pre = p->pre;

p->pre->next = q;

p->pre = q;

q->next = p;

return p;

}

5.判断蛇的死亡,分别为撞墙hit_wall()和自杀suicide()

撞墙,则只需判断蛇头的单一坐标x轴或者y轴是否与墙壁的坐标是否相等,若相等则说明蛇撞墙了

代码如下

void hit_wall(int n) //判断蛇是否撞墙,即对蛇的单一坐标x或者y进行判断,若等于墙壁的值,即游戏结束

{

if(ch == 'W'|| ch == 'S' )

if(n == 1 || n == 25) //墙壁的坐标值

{

gotoxy(0,26);

printf("游戏结束!");

printf("你的得分:%d",score);

exit(0);

}

if(ch == 'A'|| ch == 'D' )

if(n == 0 || n == 49)

{

gotoxy(0,26);

printf("游戏结束!");

printf("你的得分:%d",score);

exit(0);

}

}

自杀suicide()即蛇头是否有撞到了蛇身,做法是把蛇头的坐标拿出来,与蛇身的坐标进行对比如果相等,说明蛇头撞到了蛇身,本质上是循环链表的值进行匹配,遍历

代码如下

void suicide(struct snake *p, int x, int y) //自杀,即撞到自己本身的时候游戏结束

{

struct snake *q; //把蛇头坐标传递进来,然后与其自己身体坐标做对比若有相等则表明,蛇头撞到了蛇身

q = p;

while(q != p->next) //即对循环链表的遍历匹配

{

if(p->x == x && p->y == y)

{

gotoxy(0,26);

printf("游戏结束!");

printf("你的得分:%d",score);

exit(0);

}

else

p = p->next;

}

}

到此蛇的基本功能已经讲完,以下是全部代码。

全部代码如下

#include

#include

#include

#include

#include

#define SNAKE_SPEED 200 //蛇移动的速度

int score = 0; //成绩得分

int flag = 0; //用于判断地图上是否存在食物,0为不存在食物

int food_xy[2]; //定位食物的位置

char ch; //用来决定蛇的移动方向

struct snake //定义一条循环链表的蛇

{

int x;

int y;

struct snake *next;

struct snake *pre;

};

void HideCursor()//把蛇移动的时候产生的光标进行隐藏,隐藏光标函数

{

CONSOLE_CURSOR_INFO cursor;

cursor.bVisible = FALSE;

cursor.dwSize = sizeof(cursor);

HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);

SetConsoleCursorInfo(handle, &cursor);

}

void gotoxy(int x, int y) //定位光标函数,用来实现蛇的移动,和食物的出现(传送x,y可以将光标定位到x,y)

{

HideCursor();

COORD coord = {x,y};

SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);

}

void map() //创建蛇的地图

{

int a[25][50] = {0};

int i,j;

for(i = 0; i < 50; i++)

{

a[0][i] = 1;

a[24][i] =1;

}

for(i = 0; i < 25; i++)

{

a[i][0] = 1;

a[i][49] =1;

}

for(i = 0; i < 25; i++)

for(j = 0; j < 50; j++)

{

if(j%50 == 0)

printf("\n");

if(a[i][j] == 0)

{

printf(" ");

}

else

{

printf("#");

}

}

}

struct snake *createSnake() //给蛇进行初始化,构建一条蛇,本质为循环链表

{

int i;

struct snake *head,*p,*q;

p = q = (struct snake *)malloc(sizeof(struct snake));

head = NULL;

head = p;

head->pre = NULL;

for( i = 0; i < 5; i++)

{

p->x = 25 - i;

p->y = 13;

p->pre = head->pre;

head->pre = p;

q->next = p;

q = p;

p = (struct snake *)malloc(sizeof(struct snake));

}

q->next = head;

return head;

}

void printSnake(struct snake *p) //打印蛇,利用gotoxy()来对蛇进行打印,只需遍历一次循环链表即可将坐标可视化为一条蛇

{

struct snake *q;

q = p;

while(q != p->next) //循环链表的遍历

{

gotoxy(p->x,p->y); //根据坐标和定位光标函数来打@,实现输出蛇

printf("@");

p = p->next;

}

gotoxy(p->x,p->y);

printf("@");

gotoxy(0,0);

printf("你的得分:"); //初始化得分

}

void food() //产生食物

{

int i;

if(!flag) //根据flag的值来判断地图上是否有食物

{

srand( (unsigned)time( NULL ) );

for( i = 0; i < 2; i++ ) //对food_(x,y)来随机赋值

{

food_xy[i] = rand()%24+2;

while(food_xy[0] == 1 || food_xy[0] == 25) //这两个while为了防止食物的坐标与地图的边缘重叠

food_xy[0] = rand()%24+2;

while(food_xy[1] >= 49 || food_xy[1] == 1)

food_xy[1] =rand()%24+2;

}

gotoxy(food_xy[0],food_xy[1]); //打印食物

printf("*");

flag = 1;

}

}

struct snake *snake_link(struct snake *p) //蛇的连接

{

struct snake *q;

q = (struct snake *)malloc(sizeof(struct snake)); //即主要是实现了对循环链表的插入元素,再进行打印蛇,即可有吃到食物蛇变长的结果

q->x = food_xy[0];

q->y = food_xy[1];

q->pre = p->pre;

p->pre->next = q;

p->pre = q;

q->next = p;

return p;

}

void eat_food(struct snake *p,int x, int y) //蛇吃到食物,即主要是对蛇头的x,y坐标和food_xy的坐标进行匹配对比,若相同即调用snake_link函数即可

{

if(x == food_xy[0] && y == food_xy[1])

{

p = snake_link(p);

flag = 0;

printSnake(p);

gotoxy(8,0);

score = score + 1;

printf("%d",score);

}

}

void hit_wall(int n) //判断蛇是否撞墙,即对蛇的单一坐标x或者y进行判断,若等于墙壁的值,即游戏结束

{

if(ch == 'W'|| ch == 'S' )

if(n == 1 || n == 25)

{

gotoxy(0,26);

printf("游戏结束!");

printf("你的得分:%d",score);

exit(0);

}

if(ch == 'A'|| ch == 'D' )

if(n == 0 || n == 49)

{

gotoxy(0,26);

printf("游戏结束!");

printf("你的得分:%d",score);

exit(0);

}

}

void suicide(struct snake *p, int x, int y) //自杀,即撞到自己本身的时候游戏结束

{

struct snake *q; //把蛇头坐标传递进来,然后与其自己身体坐标做对比若有相等则表明,蛇头撞到了蛇身

q = p;

while(q != p->next) //即对循环链表的遍历匹配

{

if(p->x == x && p->y == y)

{

gotoxy(0,26);

printf("游戏结束!");

printf("你的得分:%d",score);

exit(0);

}

else

p = p->next;

}

}

struct snake *up(struct snake *p) //向上移动

{

int x;

int y;

x = p->pre->x; //将蛇头坐标赋值给x,y

y = p->pre->y;

while(p) //对循环链表的遍历,即蛇的遍历

{

Sleep(SNAKE_SPEED); //蛇移动的速度

y--; //向上移动则只需将纵坐标进行减,就可以实现蛇向上移动的效果

gotoxy(p->x,p->y); //定位到蛇尾,输出“ ”即蛇尾消失

printf(" ");

gotoxy(x, y); //定位到蛇头输出,"@",结合上面的蛇尾消失又进行蛇头打印,产生蛇移动的效果

printf("@");

suicide(p,x,y); //判断蛇头是否撞到蛇身

p = p->next; //将蛇头的坐标变为下一个

p->pre->x = x; //此时将前一个蛇头变成蛇尾,通过不断的遍历产生不断移动的效果

p->pre->y = y;

food(); //产生食物

eat_food(p,x,y); //判断是否吃到食物

hit_wall(y); //判断是否撞墙

if(kbhit()) break; //判断是否有按键输入,有就进行蛇移动方向的改变

}

return p;

}

struct snake *left(struct snake *p) //向左移动

{

int x;

int y;

x = p->pre->x;

y = p->pre->y;

while(p)

{

Sleep(SNAKE_SPEED);

x--;

gotoxy(p->x,p->y);

printf(" ");

gotoxy(x, y);

printf("@");

suicide(p,x,y);

p = p->next;

p->pre->x = x;

p->pre->y = y;

food();

eat_food(p,x,y);

hit_wall(x);

if(kbhit()) break;

}

return p;

}

struct snake *down(struct snake *p) //向下移动

{

int x;

int y;

x = p->pre->x;

y = p->pre->y;

while(p)

{

Sleep(SNAKE_SPEED);

y++;

gotoxy(p->x,p->y);

printf(" ");

gotoxy(x, y);

printf("@");

suicide(p,x,y);

p = p->next;

p->pre->x = x;

p->pre->y = y;

food();

eat_food(p,x,y);

hit_wall(y);

if(kbhit()) break;

}

return p;

}

struct snake *right(struct snake *p) //向右移动

{

int x;

int y;

x = p->pre->x;

y = p->pre->y;

while(p)

{

Sleep(SNAKE_SPEED);

x++;

gotoxy(p->x,p->y);

printf(" ");

gotoxy(x, y);

printf("@");

suicide(p,x,y);

p = p->next;

p->pre->x = x;

p->pre->y = y;

food();

eat_food(p,x,y);

hit_wall(x);

if(kbhit()) break;

}

return p;

}

void move(struct snake *p) //蛇的移动函数

{

while(1)

{

ch = getch();

switch(ch)

{

case 'W':p = up(p);break;

case 'A':p = left(p);break;

case 'D':p = right(p);break;

case 'S':p = down(p);break;

}

}

}

int main()

{

struct snake *p;

map(); //产生地图

p = createSnake(); // 初始化蛇

printSnake(p); // 打印蛇

move(p); //移动蛇

return 0;

}

更多有趣的经典小游戏实现专题,分享给大家:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个有趣的项目!首先,我们需要定义一个蛇的结构体,包含蛇头和蛇身体的位置、当前的运动方向等信息。然后,我们需要定义一个链表结构体,用于表示蛇身体的每一个节点。接下来,我们可以按照以下步骤来实现该游戏: 1. 初始化蛇的结构体和链表结构体,将蛇头和蛇身体的位置添加到链表中。 2. 在屏幕上绘制蛇头和蛇身体的位置。 3. 接受用户的输入,根据输入更新蛇的方向。 4. 根据蛇的方向移动蛇头的位置,并更新链表中蛇身体的位置。 5. 检查蛇头是否碰到边缘或自身,如果是,游戏结束。 6. 检查蛇头是否碰到食物,如果是,添加一个新的节点到链表中,并在屏幕上绘制食物。 7. 重复步骤2到步骤6,直到游戏结束。 以下是一个简单的示例代码,可能需要根据实际情况进行修改和完善: ```c #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <time.h> #include <windows.h> #define WIDTH 60 #define HEIGHT 20 #define SNAKE_LEN 3 #define FOOD_CHAR '*' typedef struct _snake_node { int x; int y; struct _snake_node *next; } SnakeNode; typedef struct _snake { int x; int y; int direction; SnakeNode *body; } Snake; void init_snake(Snake *snake, int x, int y) { snake->x = x; snake->y = y; snake->direction = 'a'; snake->body = (SnakeNode *)malloc(sizeof(SnakeNode)); snake->body->x = x; snake->body->y = y; snake->body->next = NULL; } void add_node_to_snake(Snake *snake, int x, int y) { SnakeNode *new_node = (SnakeNode *)malloc(sizeof(SnakeNode)); new_node->x = x; new_node->y = y; new_node->next = snake->body; snake->body = new_node; } void draw_snake(Snake *snake) { SnakeNode *node = snake->body; while (node) { printf("%c[%d;%dH#", 27, node->y, node->x); node = node->next; } } void move_snake(Snake *snake) { int dx = 0, dy = 0; switch (snake->direction) { case 'a': dx = -1; break; case 'd': dx = 1; break; case 'w': dy = -1; break; case 's': dy = 1; break; } int x = snake->x + dx; int y = snake->y + dy; add_node_to_snake(snake, x, y); snake->x = x; snake->y = y; SnakeNode *node = snake->body; while (node->next->next) { node = node->next; } free(node->next); node->next = NULL; } void reset_console() { system("cls"); printf("%c[?25l", 27); // hide cursor for (int i = 1; i <= WIDTH; i++) { printf("%c[%d;%dH#", 27, 1, i); printf("%c[%d;%dH#", 27, HEIGHT, i); } for (int i = 2; i <= HEIGHT - 1; i++) { printf("%c[%d;%dH#", 27, i, 1); printf("%c[%d;%dH#", 27, i, WIDTH); } } void draw_food(int x, int y) { printf("%c[%d;%dH%c", 27, y, x, FOOD_CHAR); } int main() { srand(time(NULL)); Snake snake; init_snake(&snake, WIDTH / 2, HEIGHT / 2); draw_snake(&snake); int food_x = rand() % (WIDTH - 2) + 2; int food_y = rand() % (HEIGHT - 2) + 2; draw_food(food_x, food_y); while (1) { if (_kbhit()) { int ch = _getch(); if (ch == 0xE0 || ch == 0) { ch = _getch(); switch (ch) { case 75: snake.direction = 'a'; break; case 77: snake.direction = 'd'; break; case 72: snake.direction = 'w'; break; case 80: snake.direction = 's'; break; } } else if (ch == 'q') { break; } } move_snake(&snake); reset_console(); draw_snake(&snake); draw_food(food_x, food_y); if (snake.x == 1 || snake.x == WIDTH || snake.y == 1 || snake.y == HEIGHT) { printf("%c[%d;%dHGame over!", 27, HEIGHT / 2, WIDTH / 2 - 5); break; } else if (snake.x == food_x && snake.y == food_y) { food_x = rand() % (WIDTH - 2) + 2; food_y = rand() % (HEIGHT - 2) + 2; draw_food(food_x, food_y); } else { Sleep(100); } } printf("%c[?25h", 27); // show cursor return 0; } ``` 在 Windows 系统上编译运行该代码,即可看到贪吃蛇游戏的效果。注意,该代码仅供参考,可能存在一些问题和不足之处,需要根据实际情况进行调整和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值