一个控制台贪吃蛇小游戏(wsad控制移动)

  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 }
原文地址:https://www.cnblogs.com/doodle777/p/3154450.html