贪吃蛇
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <conio.h> 3 #include <stdlib.h> 4 #include <windows.h> 5 #include <time.h> 6 #define MAX__X 23 7 #define MAX__Y 50 8 #define MAX_FOOD 50 9 #define ESC 27 10 #define SPACE 32 11 12 typedef struct Node 13 { 14 int x; 15 int y; 16 struct Node *next; 17 } Node,*LinkList; 18 19 typedef struct 20 { 21 LinkList front; 22 LinkList rear; 23 int length; 24 } Queue; 25 26 Queue snake; 27 28 void gotoxy(int x,int y)//坐标定位 29 { 30 COORD loc; 31 loc.X = y; 32 loc.Y = x; 33 SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), loc); 34 } 35 36 void help_info()//显示帮助信息 37 { 38 gotoxy(8,55); 39 puts("按ESC键退出,空格键暂停:"); 40 gotoxy(10,55); 41 puts("上,下,左,右:w,s,a,d"); 42 gotoxy(12,55); 43 puts("蛇越长,速度也会越快:"); 44 gotoxy(14,55); 45 puts("如无法控制蛇,请关闭"); 46 gotoxy(15,56); 47 puts("大写键盘锁定状态:"); 48 } 49 50 void game_info()//显示游戏信息 51 { 52 gotoxy(3,60); 53 printf("当前蛇长度: %d",snake.length); 54 gotoxy(5,60); 55 printf(" "); 56 gotoxy(5,60); 57 printf("离胜利还差: %d",MAX_FOOD-snake.length); 58 } 59 60 void enqueue(int x,int y)//入队 61 { 62 LinkList p; 63 p = (LinkList)malloc(sizeof(Node)); 64 p->x = x; 65 p->y = y; 66 snake.rear->next = p; 67 snake.rear = p; 68 p->next = NULL; 69 snake.length++; 70 } 71 72 void dequeue()//出队 73 { 74 LinkList p = snake.front; 75 //保存食物位置 76 p->next->x = p->x; 77 p->next->y = p->y; 78 snake.front = snake.front->next; 79 snake.length--; 80 free(p); 81 } 82 83 void destroy_queue()//销毁队列 84 { 85 LinkList p; 86 while(p = snake.front) 87 { 88 snake.front = snake.front->next; 89 free(p); 90 } 91 } 92 93 void snake_init()//初始化蛇,rear指向蛇头,front指向食物,front->next指向蛇尾 94 { 95 int i; 96 snake.rear = snake.front = (LinkList)malloc(sizeof(Node)); 97 snake.rear->next = NULL; 98 snake.length = 0; 99 for(i = 0; i < 3; i++) 100 { 101 enqueue(1,i + 1); 102 } 103 } 104 105 void show_food()//随机化食物位置 106 { 107 LinkList p; 108 srand(time(NULL));//初始化随机种子 109 while(1) 110 { 111 snake.front->x = rand() % (MAX__X-1) + 1; 112 snake.front->y = rand() % (MAX__Y-1) + 1; 113 p = snake.front->next; 114 //防止食物出现在蛇内部 115 while(p) 116 { 117 if(snake.front->x == p->x && snake.front->y == p->y) 118 { 119 break; 120 } 121 else 122 { 123 p = p->next; 124 } 125 } 126 if(!p) 127 { 128 break; 129 } 130 } 131 gotoxy(snake.front->x,snake.front->y); 132 putchar('@');//食物 133 } 134 135 int judge()//判断失败与否 136 { 137 LinkList p; 138 if(snake.length >= MAX_FOOD) 139 { 140 system("cls"); 141 gotoxy(4,20); 142 puts("恭喜你,赢了!!!"); 143 exit(0); 144 } 145 //碰到自身 146 p = snake.front->next; 147 while(snake.rear != p) 148 { 149 if(snake.rear->x == p->x && snake.rear->y == p->y) 150 { 151 break; 152 } 153 else 154 { 155 p = p->next; 156 } 157 } 158 if(snake.rear == p) 159 { 160 //碰到边界 161 if(snake.rear->x >= 1 && snake.rear->y >= 1 && snake.rear->x < MAX__X && snake.rear->y < MAX__Y) 162 { 163 return 1; 164 } 165 } 166 system("cls"); 167 gotoxy(4,20); 168 puts("GAME OVER!!!"); 169 destroy_queue(); 170 getch(); 171 exit(0); 172 } 173 174 void drow_wall()//画墙 175 { 176 int i; 177 for(i = 0; i <= MAX__Y; i++) 178 { 179 gotoxy(0,i); 180 putchar('W'); 181 gotoxy(MAX__X,i); 182 putchar('M'); 183 if(i <= MAX__X) 184 { 185 gotoxy(i,0); 186 putchar('I'); 187 gotoxy(i,MAX__Y); 188 putchar('I'); 189 } 190 } 191 } 192 193 void drow_snake(int i)//0表示画蛇头,1表示画蛇身 194 { 195 LinkList p; 196 p = snake.rear; 197 gotoxy(p->x,p->y); 198 if(i) 199 { 200 putchar('*'); //蛇身 201 } 202 else 203 { 204 putchar('%'); //蛇头 205 } 206 } 207 208 void clear_snake_tail() 209 { 210 LinkList p = snake.front->next; 211 gotoxy(p->x,p->y); 212 putchar(' ');//清除旧蛇尾 213 p = p->next; 214 gotoxy(p->x,p->y); 215 putchar('~');//添加新蛇尾 216 } 217 218 void snake_auto_move(char temp)//实现蛇的自动移动 219 { 220 int x,y,speed; 221 do 222 { 223 clear_snake_tail(); 224 drow_snake(1);//画蛇身 225 x = snake.rear->x; 226 y = snake.rear->y; 227 switch(temp) 228 { 229 case 'w': 230 x--; 231 break; 232 case 's': 233 x++; 234 break; 235 case 'a': 236 y--; 237 break; 238 case 'd': 239 y++; 240 } 241 enqueue(x,y);//新蛇头入队 242 if(snake.front->x == x && snake.front->y == y) //蛇捕捉到食物后,食物重新随机化 243 { 244 game_info(); 245 show_food(); 246 } 247 else 248 { 249 dequeue(); //旧蛇尾出队 250 } 251 drow_snake(0);//画蛇头 252 speed = -2.3 * snake.length + 157; 253 Sleep(speed);//程序暂停speed个单位毫秒 254 } 255 while(!_kbhit() && judge()); //_kbhit为检测键盘输入 256 } 257 258 void snake_move()//实现玩家控制蛇的移动 259 { 260 char c,pause; 261 static char temp = 0;//静态局部变量 262 pause = 0; 263 if(!temp) //一开始的时候让蛇先自动移动 264 { 265 temp = 'd'; 266 snake_auto_move(temp); 267 } 268 while(1) 269 { 270 c = getch(); 271 if(c == ESC) //退出 272 { 273 system("cls"); 274 puts("游戏退出成功!"); 275 system("pause"); 276 destroy_queue(); 277 exit(0); 278 } 279 if(pause == SPACE) 280 { 281 if(c == SPACE) //再按下空格键继续游戏 282 { 283 pause = 0; 284 gotoxy(6,20); 285 printf(" ");//消除~~Pause~~: 286 snake_auto_move(temp); 287 } 288 continue; 289 } 290 if(c == SPACE) //按空格键暂停游戏 291 { 292 pause = SPACE; 293 gotoxy(6,20); 294 printf("~~Pause~~:"); 295 continue; 296 } 297 if(c == 'w' || c == 'a' || c == 's' || c == 'd') 298 { 299 if((temp == 'w' && c == 's') || (temp == 's' && c == 'w') || (temp == 'd' && c == 'a') || (temp == 'a' && c == 'd')) //不允许连续的两次内按相反的键 300 { 301 snake_auto_move(temp); 302 continue; 303 } 304 break; 305 } 306 snake_auto_move(temp); 307 } 308 temp = c; 309 snake_auto_move(temp); 310 } 311 312 int main() 313 { 314 help_info(); 315 snake_init(); 316 show_food(); 317 drow_wall(); 318 game_info(); 319 while(judge()) 320 { 321 snake_move(); 322 } 323 return 0; 324 }