源代码下载地址为: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));//为了防止每次产生的随机数相同,种子设置为time 111 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,右R 142 { 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; //保证最低分为1 373 } 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 }
原博客地址:http://www.cnblogs.com/jacklu/p/5214692.html