1 /******************************************** 2 * 程序名称:MR.DUAN 的贪吃蛇游戏(链表法) 3 * 作 者:WindAutumn <fluttingleaves@hotmail.com> 4 * 最后修改:2012-7-25-PM 5 * 版 本 号:1.3 6 * 7 * 8 * 以后有空再修改 9 * *****************************************/ 10 11 #include<stdio.h> 12 #include<windows.h> 13 #include<conio.h> 14 #include<time.h> 15 16 #define MAXWIDE 80 17 #define MAXHIGH 24 18 19 typedef struct 20 { 21 int x; 22 int y; 23 } POSITION; // 食物,节点 24 25 typedef struct snackbody 26 { 27 POSITION body; 28 snackbody * link; 29 } SNACK; // 蛇身的链表 30 31 void StartGame(); 32 void InitScreen(HANDLE hSnack); 33 void HideCursor(HANDLE hSnack); 34 void GotoXY(HANDLE hSnack, int x, int y); 35 36 void PrintRandFood(HANDLE hSnack, POSITION * food); 37 void PrintSnack(HANDLE hSnack, SNACK * snack, int mode); 38 //int HeadDirection(); 39 SNACK * SnackHeadWalk(SNACK * snack, int direction); 40 void IsDied(HANDLE hSnack, SNACK * snack, POSITION * food); 41 void GameOver(HANDLE hSnack); 42 43 void main() 44 { 45 system("color 7b");// 白色背景 46 SetConsoleTitle("MR.DUAN 的贪吃蛇游戏"); 47 StartGame(); 48 } 49 50 void StartGame() 51 { 52 POSITION food; 53 SNACK * snack = (SNACK *)malloc(sizeof(SNACK)); 54 char length = 0;// 定义长度 55 int direction_get = 0;// 定义获取的方向 56 int direction_last = 0;// 定义之后的方向 57 int key_direct;// 按下的按键 58 int foodflag = 0;// 食物是否存在,1--是,0--否 59 60 HANDLE hSnack = GetStdHandle(STD_OUTPUT_HANDLE); 61 HideCursor(hSnack); 62 InitScreen(hSnack); 63 64 srand(time(NULL));// 初始化随机数生成器,以便产生随机 食物 65 snack->body.x = 40;// 蛇头 66 snack->body.y = 12; 67 snack->link = NULL; 68 69 PrintSnack(hSnack, snack, 0);// mode 0 打印初始蛇头 70 Sleep(500); 71 while(1)// 贪吃蛇操作 72 { 73 if(_kbhit()) 74 { 75 key_direct = getch(); 76 switch(key_direct) 77 { 78 case 'w' : 79 direction_get = 1; 80 break;// 上// 键盘四按键的逆序 81 case 'a' : 82 direction_get = 2; 83 break;// 左 84 case 's' : 85 direction_get = 3; 86 break;// 下 87 case 'd' : 88 direction_get = 4; 89 break;// 右 90 } 91 } 92 if((direction_last != direction_get + 2)&&(direction_last != direction_get - 2)) 93 direction_last = direction_get;// 如果行进方向和获取方向不为相反,则改变行进方向 94 snack = SnackHeadWalk(snack, direction_last); 95 96 if(0 == foodflag) 97 { 98 PrintRandFood(hSnack, &food);// 如果食物已经被吃,则产生新的食物 99 foodflag = 1;// 食物标记为 未吃 100 } 101 102 if(snack->body.x == food.x && snack->body.y == food.y)// 头碰到食物 103 { 104 PrintSnack(hSnack, snack, 0);// 只打头不去尾 105 foodflag = 0;// 食物被吃,没有食物了 106 length++; 107 } 108 else 109 { 110 PrintSnack(hSnack, snack, 0);// 打头 111 PrintSnack(hSnack, snack, 1);// 去尾 112 } 113 IsDied(hSnack, snack, &food); 114 Sleep(500); 115 } 116 } 117 118 void InitScreen(HANDLE hSnack)// 打印周围红框框 119 { 120 int i; 121 SetConsoleTextAttribute(hSnack, FOREGROUND_INTENSITY | FOREGROUND_RED | 122 BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED);// 红色字体,白色背景 123 GotoXY(hSnack, 0, 0); 124 printf("╔"); 125 for(i=1; i<(MAXWIDE-1)/2; i++) 126 printf("═"); 127 printf("╗"); 128 129 for(i=1; i< MAXHIGH; i++) 130 { 131 GotoXY(hSnack, 0, i); 132 printf("║"); 133 GotoXY(hSnack, MAXWIDE-2, i); 134 printf("║"); 135 } 136 137 GotoXY(hSnack, 0, MAXHIGH); 138 printf("╚"); 139 for(i=1; i<(MAXWIDE-1)/2; i++) 140 printf("═"); 141 printf("╝"); 142 143 GotoXY(hSnack, 0, 0); 144 } 145 146 void HideCursor(HANDLE hSnack) 147 { 148 CONSOLE_CURSOR_INFO cursor_info = {1, 0}; 149 SetConsoleCursorInfo(hSnack, &cursor_info); 150 } 151 152 void GotoXY(HANDLE hSnack, int x, int y) 153 { 154 COORD coord; 155 coord.X = x; 156 coord.Y = y; 157 SetConsoleCursorPosition(hSnack, coord); 158 } 159 160 void PrintRandFood(HANDLE hSnack, POSITION * food)// 2--78 中的偶数, 1--23 161 { 162 food->x = (rand()%76 + 2)/2*2; 163 food->y = rand()%22 + 1; 164 SetConsoleTextAttribute(hSnack,FOREGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED); 165 GotoXY(hSnack, food->x, food->y); 166 printf("█"); 167 } 168 169 void PrintSnack(HANDLE hSnack, SNACK * snack, int mode) 170 { 171 if(0 == mode) 172 { 173 GotoXY(hSnack, snack->body.x, snack->body.y); 174 SetConsoleTextAttribute(hSnack,FOREGROUND_BLUE | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED); 175 printf("□"); 176 } 177 if(1 == mode) 178 { 179 SNACK * ptail, *pnext; 180 ptail = snack; 181 pnext = ptail->link; 182 while(pnext->link!=NULL) 183 { 184 ptail = ptail->link; 185 pnext = ptail->link; 186 } 187 GotoXY(hSnack, pnext->body.x, pnext->body.y); 188 printf(" "); 189 ptail->link = NULL; 190 free(pnext); 191 } 192 } 193 194 /*int HeadDirection() 195 { 196 HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); 197 INPUT_RECORD inRec; 198 DWORD res; 199 200 ReadConsoleInput(hInput, &inRec, 0, &res); 201 if(inRec.EventType == KEY_EVENT) 202 { 203 switch(inRec.Event.KeyEvent.wVirtualKeyCode) 204 { 205 case VK_UP : return 1; 206 case VK_DOWN : return 2; 207 case VK_LEFT : return 3; 208 case VK_RIGHT : return 4; 209 } 210 } 211 return 0; 212 }*/ 213 214 SNACK * SnackHeadWalk(SNACK * snack, int direction) 215 { 216 // 0为默认值,默认向右,1为向上,2为向下,3为向左,4为向右 217 218 SNACK * newhead = (SNACK * )malloc(sizeof(SNACK)); 219 switch(direction) 220 { 221 case 1 : 222 newhead->body.x = snack->body.x; 223 newhead->body.y = snack->body.y - 1; 224 break; 225 case 3 : 226 newhead->body.x = snack->body.x; 227 newhead->body.y = snack->body.y + 1; 228 break; 229 case 2 : 230 newhead->body.x = snack->body.x - 2; 231 newhead->body.y = snack->body.y; 232 break; 233 case 0 : 234 case 4 : 235 newhead->body.x = snack->body.x + 2; 236 newhead->body.y = snack->body.y; 237 break; 238 } 239 newhead->link = snack; 240 return newhead; 241 } 242 243 void IsDied(HANDLE hSnack, SNACK * snack, POSITION * food) 244 { 245 SNACK * pCompare = snack; 246 if(snack->body.x == 0 || snack->body.y ==0 || snack->body.x == MAXWIDE ||snack->body.y == MAXHIGH) 247 GameOver(hSnack);// 撞墙死亡 248 while(pCompare->link!=NULL) 249 { 250 if(pCompare->body.x == snack->body.x && pCompare->body.y == snack->body.y && pCompare!=snack) 251 GameOver(hSnack);// 吃到自己死亡 252 pCompare = pCompare->link; 253 } 254 } 255 256 void GameOver(HANDLE hSnack) 257 { 258 GotoXY(hSnack, MAXWIDE/2, MAXHIGH/2); 259 printf("GAME OVER!"); 260 GotoXY(hSnack, MAXWIDE/2, MAXHIGH/2 + 1); 261 printf("PRESS ANY KEY TO EXIT."); 262 getch(); 263 exit(0); 264 }