当前位置:首页 > 通信资讯 > 正文

c语言写贪吃蛇链表(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,输出“#”,产生一个地图。

代码如下:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 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为全局变量)
代码如下

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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()函数进行展示

代码如下

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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])随机产生食物
代码如下

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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(),则我们只需判断蛇头是否和食物的坐标重叠,若重叠则表明蛇吃到了食物

代码如下

?
1 2 3 4 5 6 7 8 9 10 11 12 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()函数

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

c语言写贪吃蛇链表(C语言循环链表)

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

?
1 2 3 4 5 6 7 8 9 10 11 12 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轴是否与墙壁的坐标是否相等,若相等则说明蛇撞墙了
代码如下

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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()即蛇头是否有撞到了蛇身,做法是把蛇头的坐标拿出来,与蛇身的坐标进行对比如果相等,说明蛇头撞到了蛇身,本质上是循环链表的值进行匹配,遍历

代码如下

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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; } }

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

全部代码如下

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 #include <stdio.h> #include <stdlib.h> #include <windows.h> #include <conio.h> #include <time.h> #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; }

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

原文链接:https://blog.csdn.net/weixin_46571879/article/details/109538169

如果您对该产品感兴趣,请填写办理(客服微信:xiaoxiongyidong)

为您推荐:

发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。