2019-08-27
贪吃蛇游戏C语言源代码学习
源代码下载地址为:www.clang.cc
阅读学习了源代码,并做了简单的注释和修改,里面只用了链表数据结构,非常适合C语言入门者学习阅读。
程序可在VS2013下编译运行。
1 #include<stdio.h> 2 #include<time.h> 3 #include<windows.h> 4 #include<stdlib.h> 5 6 #define U 1 7 #define D 2 8 #define L 3
9 #define R 4 //蛇的状态,U:上 ;D:下;L:左 R:右 10 11 typedef struct SNAKE //蛇身的一个节点 12 { 13 int x; 14 int y; 15 struct SNAKE *next; 16 }snake; 17 18 //全局变量// 19 int score = 0, add = 10;//总得分与每次吃食物得分。 20 int status, sleeptime = 200;//每次运行的时间间隔 21 snake *head, *food;//蛇头指针,食物指针 22 snake *q;//遍历蛇的时候用到的指针 23 int endGamestatus = 0; //游戏结束的情况,1:撞到墙;2:咬到自己;3:主动退出游戏。 24 25 //声明全部函数// 26 void Pos(); 27 void creatMap(); 28 void initSnake(); 29 int biteSelf(); 30 void createFood(); 31 void cantCrossWall(); 32 void snakeMove(); 33 void pause(); 34 void runGame(); 35 void initGame(); 36 void endGame(); 37 void gameStart(); 38 39 void Pos(int x, int y)//设置光标位置 40 { 41 COORD pos; 42 HANDLE hOutput; 43 pos.X = x; 44 pos.Y = y; 45 hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//返回标准的输入、输出或错误的设备的句柄,也就是获得输入、输出/错误的屏幕缓冲区的句柄 46 SetConsoleCursorPosition(hOutput, pos); 47 } 48 49 void creatMap()//创建地图 50 { 51 int i; 52 for (i = 0; i<58; i += 2)//打印上下边框 53 { 54 Pos(i, 0); 55 printf("■");//一个方块占两个位置 56 Pos(i, 26); 57 printf("■"); 58 } 59 for (i = 1; i<26; i++)//打印左右边框 60 { 61 Pos(0, i); 62 printf("■"); 63 Pos(56, i); 64 printf("■"); 65 } 66 } 67 68 void initSnake()//初始化蛇身 69 { 70 snake *tail; 71 int i; 72 tail = (snake*)malloc(sizeof(snake));//从蛇尾开始,头插法,以x,y设定开始的位置// 73 tail->x = 24; 74 tail->y = 5; 75 tail->next = NULL; 76 for (i = 1; i <= 4; i++)//初始长度为4 77 { 78 head = (snake*)malloc(sizeof(snake)); 79 head->next = tail; 80 head->x = 24 + 2 * i; 81 head->y = 5; 82 tail = head; 83 } 84 while (tail != NULL)//从头到为,输出蛇身 85 { 86 Pos(tail->x, tail->y); 87 printf("■"); 88 tail = tail->next; 89 } 90 } 91 //?? 92 int biteSelf()//判断是否咬到了自己 93 { 94 snake *self; 95 self = head->next; 96 while (self != NULL) 97 { 98 if (self->x == head->x && self->y == head->y) 99 {100 return 1;101 }
102 self = self->next;103 }104 return 0;105 }106 107 void createFood()//随机出现食物108 {109 snake *food_1;110 srand((unsigned)time(NULL));//为了防止每次产生的随机数相同,种子设置为time111 food_1 = (snake*)malloc(sizeof(snake));112 while ((food_1->x % 2) != 0) //保证其为偶数,使得食物能与蛇头对其113 {114 food_1->x = rand() % 52 + 2;115 }116 food_1->y = rand() % 24 + 1;117 q = head;118 while (q->next == NULL)119 {120 if (q->x == food_1->x && q->y == food_1->y) //判断蛇身是否与食物重合121 {122 free(food_1);123 createFood();124 }125 q = q->next;126 }127 Pos(food_1->x, food_1->y);128 food = food_1;129 printf("■");130 }131 132 void cantCrossWall()//不能穿墙133 {134 if (head->x == 0 || head->x == 56 || head->y == 0 || head->y == 26)135 {136 endGamestatus = 1;137 endGame();138 }139 }140 141 void snakeMove()//蛇前进,上U,下D,左L,右R142 {143 snake * nexthead;144 cantCrossWall();145 146 nexthead = (snake*)malloc(sizeof(snake));147 if (status == U)148 {149 nexthead->x = head->x;150 nexthead->y = head->y - 1;151 if (nexthead->x == food->x && nexthead->y == food->y)//如果下一个有食物//152 {153 nexthead->next = head;154 head = nexthead;155 q = head;156 while (q != NULL)157 {158 Pos(q->x, q->y);159 printf("■");160 q = q->next;161 }162 score = score + add;163 createFood();164 }165 else //如果没有食物//166 {167 nexthead->next = head;168 head = nexthead;169 q = head;170 while (q->next->next != NULL)171 {172 Pos(q->x, q->y);173 printf("■");174 q = q->next;175 }176 Pos(q->next->x, q->next->y);177 printf(" ");178 free(q->next);179 q->next = NULL;180 }181 }182 if (status == D)183 {184 nexthead->x = head->x;185 nexthead->y = head->y + 1;186 if (nexthead->x == food->x && nexthead->y == food->y) //有食物187 {188 nexthead->next = head;189 head = nexthead;190 q = head;191 while (q != NULL)192 {193 Pos(q->x, q->y);194 printf("■");195 q = q->next;196 }197 score = score + add;198 createFood();199 }200 else //没有食物201 {202 nexthead->next = head;203 head = nexthead;204 q = head;205 while (q->next->next != NULL)206 {207 Pos(q->x, q->y);208 printf("■");209 q = q->next;210 }211 Pos(q->next->x, q->next->y);212 printf(" ");213 free(q->next);214 q->next = NULL;215 }216 }217 if (status == L)218 {219 nexthead->x = head->x - 2;220 nexthead->y = head->y;221 if (nexthead->x == food->x && nexthead->y == food->y)//有食物222 {223 nexthead->next = head;224 head = nexthead;225 q = head;226 while (q != NULL)227 {228 Pos(q->x, q->y);229 printf("■");230 q = q->next;231 }232 score = score + add;233 createFood();234 }235 else //没有食物236 {237 nexthead->next = head;238 head = nexthead;239 q = head;240 while (q->next->next != NULL)241 {242 Pos(q->x, q->y);243 printf("■");244 q = q->next;245 }246 Pos(q->next->x, q->next->y);247 printf(" ");248 free(q->next);249 q->next = NULL;250 }251 }252 if (status == R)253 {254 nexthead->x = head->x + 2;255 nexthead->y = head->y;256 if (nexthead->x == food->x && nexthead->y == food->y)//有食物257 {258 nexthead->next = head;259 head = nexthead;260 q = head;261 while (q != NULL)262 {263 Pos(q->x, q->y);264 printf("■");265 q = q->next;266 }267 score = score + add;268 createFood();269 }270 else //没有食物271 {272 nexthead->next = head;273 head = nexthead;274 q = head;275 while (q->next->next != NULL)276 {277 Pos(q->x, q->y);278 printf("■");279 q = q->next;280 }281 Pos(q->next->x, q->next->y);282 printf(" ");283 free(q->next);284 q->next = NULL;285 }286 }287 if (biteSelf() == 1) //判断是否会咬到自己288 {289 endGamestatus = 2;290 endGame();291 }292 }293 294 void pause()//暂停295 {296 while (1)297 {298 Sleep(300);299 if (GetAsyncKeyState(VK_SPACE))300 {301 break;302 }303 304 }305 }306 307 void runGame()//控制游戏 308 {309 310 Pos(64, 15);311 printf("不能穿墙,不能咬到自己\n");312 Pos(64, 16);313 printf("用↑.↓.←.→分别控制蛇的移动.");314 Pos(64, 17);315 printf("F1 为加速,F2 为减速\n");316 Pos(64, 18);317 printf("ESC :退出游戏.space:暂停游戏.");318 Pos(64, 20);319 printf("C语言研究中心 www.clang.cc");320 status = R;321 while (1)322 {323 Pos(64, 10);324 printf("得分:%d ", score);325 Pos(64, 11);326 printf("每个食物得分:%d分", add);327 if (GetAsyncKeyState(VK_UP) && status != D)328 {329 status = U;330 }331 else if (GetAsyncKeyState(VK_DOWN) && status != U)332 {333 status = D;334 }335 else if (GetAsyncKeyState(VK_LEFT) && status != R)336 {337 status = L;338 }339 else if (GetAsyncKeyState(VK_RIGHT) && status != L)340 {341 status = R;342 }343 else if (GetAsyncKeyState(VK_SPACE))344 {345 pause();346 }347 else if (GetAsyncKeyState(VK_ESCAPE))348 {349 endGamestatus = 3;350 break;351 }352 else if (GetAsyncKeyState(VK_F1))353 {354 if (sleeptime >= 50)355 {356 sleeptime = sleeptime - 30;357 add = add + 2;358 if (sleeptime == 320)359 {360 add = 2;//防止减到1之后再加回来有错361 }362 }363 }364 else if (GetAsyncKeyState(VK_F2))365 {366 if (sleeptime<350)367 {368 sleeptime = sleeptime + 30;369 add = add - 2;370 if (sleeptime == 350)371 {372 add = 1; //保证最低分为1373 }374 }375 }376 Sleep(sleeptime);377 snakeMove();378 }379 }380 381 void initGame()//开始界面382 {383 Pos(40, 12);384 385 system("title C语言研究中心 www.clang.cc");386 printf("欢迎来到贪食蛇游戏!");387 Pos(40, 25);388 printf(" C语言研究中心 www.clang.cc.\n");389 system("pause");390 system("cls");391 Pos(25, 12);392 printf("用↑.↓.←.→分别控制蛇的移动, F1 为加速,2 为减速\n");393 Pos(25, 13);394 printf("加速将能得到更高的分数。\n");395 system("pause");396 system("cls");397 }398 399 void endGame()//结束游戏400 {401 402 system("cls");403 Pos(24, 12);404 if (endGamestatus == 1)405 {406 printf("对不起,您撞到墙了。游戏结束.");407 }408 else if (endGamestatus == 2)409 {410 printf("对不起,您咬到自己了。游戏结束.");411 }412 else if (endGamestatus == 3)413 {414 printf("您的已经结束了游戏。");415 }416 Pos(24, 13);417 printf("您的得分是%d\n", score);418 while (getchar() != 'y')419 {
420 printf("close?[y]");421 }422 exit(0);423 }424 425 void gameStart()//游戏初始化426 {427 system("mode con cols=100 lines=30");428 initGame();429 creatMap();430 initSnake();431 createFood();432 }433 434 int main()435 {436 gameStart();437 runGame();438 endGame();439 return 0;440 }