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 }