基于C++控制台实现的贪吃蛇

本文为大大维原创,最早于博客园发表,转载请注明出处!!!

 

虽然本人一直是个免费的游戏测试员(/手动滑稽),但一直有着一个游戏架构师的梦想。正如马爸爸所说,梦想还是要有的,万一实现了呢?

这些天放寒假,有些空闲时间,就想着做一个简单的游戏机。能达到小时候十几块钱买的那种小霸王的功能就差不多了(有贪吃蛇,赛车小游戏,俄罗斯方块,雷霆战机,坦克大战,2048,拼图等),好吧,原谅我有些浮夸风(/手动斜眼)。。。

这不,下面是我这两天抠出来的一个最简单的贪吃蛇小游戏,姑且叫它“大大维的贪吃蛇v1”吧!!!

游戏功能比较简单,后续还需要完善。先将代码在这保存一份,日后看看,也是一件挺有意思的事情吧!!!

  1 /**--------------------------------------------------**/
  2 /**名称:大大维的贪吃蛇v1             日期:2017/1/22**/
  3 /**描述:实现了贪吃蛇的基本功能,可以调节游戏难度,**/
  4 /**做了一个简单的用户界面                           **/
  5 /**存在的问题:由于使用了全局数组存贮,因此对Space **/
  6 /**类的封装有些欠缺;由于使用了全局刷新,游戏运行中**/
  7 /**会出现闪屏现象,游戏难度越高,闪动越严重;不能够**/
  8 /**存储玩家的游戏记录,由于不是图形化界面,用户界面**/
  9 /**较丑;不能改变游戏的地图大小                      **/
 10 /**笔者会在后续版本逐步完善这些问题!!!              **/
 11 /**--------------------------------------------------**/
 12 
 13 #include<iostream>
 14 #include<ctime>
 15 #include<cstdlib>
 16 #include<cstdio>
 17 #include<conio.h>
 18 #include<windows.h>
 19 using namespace std;
 20 const int SpaceLENG=20;
 21 const int SpaceHIGH=40;
 22 const int HARDSPEED=100;
 23 const int NOMALSPEED=400;
 24 const int EASYSPEED=700;
 25 int speed=NOMALSPEED;
 26 bool FLAG=true;
 27 enum dir {UP,DOWN,LEFT,RIGHT};///使用小写会引发歧义
 28 enum level {HARD,ESAY,NOMAL};
 29 ///----------------------------------------------------
 30 ///游戏空间定义
 31 class Space
 32 {
 33 public:
 34     void InitSpace();
 35     void DisplaySpace();
 36 public:
 37     char SpaceData[SpaceLENG+2][SpaceHIGH+2];
 38 };
 39 void Space::InitSpace()
 40 {
 41     for(int i=-1; i<SpaceLENG+1; i++)
 42         for(int j=-1; j<SpaceHIGH+1; j++)
 43         {
 44             if(i<0||i==SpaceLENG||j<0||j==SpaceHIGH)
 45                 SpaceData[i][j]='#';
 46             else
 47                 SpaceData[i][j]=' ';
 48         }
 49 }
 50 void Space::DisplaySpace()
 51 {
 52     for(int i=-1; i<SpaceLENG+1; i++)
 53     {
 54         for(int j=-1; j<SpaceHIGH+1; j++)
 55         {
 56             cout<<SpaceData[i][j];
 57         }
 58         cout<<endl;
 59     }
 60     cout<<endl<<endl;
 61 }
 62 Space *spa=new Space();
 63 ///----------------------------------------------------
 64 ///蛇节点定义
 65 class SnakeNode
 66 {
 67 public:
 68     void setXY(int m,int n)
 69     {
 70         x=m;
 71         y=n;
 72     }
 73     void setNext(SnakeNode *temp)
 74     {
 75         next=temp;
 76     }
 77     void setPrior(SnakeNode *temp)
 78     {
 79         prior=temp;
 80     }
 81     int getX()
 82     {
 83         return x;
 84     }
 85     int getY()
 86     {
 87         return y;
 88     }
 89     SnakeNode* getNext()
 90     {
 91         return next;
 92     }
 93     SnakeNode* getPrior()
 94     {
 95         return prior;
 96     }
 97 private:
 98     int x,y;
 99     SnakeNode *prior,*next;
100 };
101 ///----------------------------------------------------
102 ///食物定义
103 class Food
104 {
105 public:
106     void foodCreate()
107     {
108         bool flag=true;
109         while(flag)
110         {
111             srand((unsigned int)time(NULL));
112             fx=rand()%SpaceLENG;
113             fy=rand()%SpaceHIGH;
114             if(spa->SpaceData[fx][fy]!='*')
115                 flag=false;
116         }
117 
118         spa->SpaceData[fx][fy]='$';
119     }
120     int getFx()
121     {
122         return fx;
123     }
124     int getFy()
125     {
126         return fy;
127     }
128 private:
129     int fx;
130     int fy;
131 };
132 ///----------------------------------------------------
133 ///蛇定义
134 class Snake:public SnakeNode,public Food
135 {
136 public:
137     Snake()
138     {
139         addHead(SpaceLENG/2,SpaceHIGH/2);
140         addHead(SpaceLENG/2,SpaceHIGH/2-1);
141         addHead(SpaceLENG/2,SpaceHIGH/2-2);
142     }
143     void addHead(int x,int y);
144     void delTail();
145     void moving();
146     void changePoint(char keydown);
147     SnakeNode* getHead()
148     {
149         return head;
150     }
151     SnakeNode* getTail()
152     {
153         return tail;
154     }
155     int getLEN()
156     {
157         return LEN;
158     }
159 private:
160     SnakeNode *head=NULL,*tail=NULL;
161     int LEN=0;
162     dir point=LEFT;
163 };
164 void Snake::addHead(int x,int y)
165 {
166     SnakeNode *temp=new SnakeNode();
167     temp->setXY(x,y);
168     temp->setNext(head);
169     temp->setPrior(NULL);
170     if(head)
171     {
172         head->setPrior(temp);///如果头不为空
173         spa->SpaceData[head->getX()][head->getY()]='*';///旧头
174     }
175     head=temp;
176     if(!tail)tail=head;///如果尾为空
177     spa->SpaceData[head->getX()][head->getY()]='@';///新头
178     LEN++;
179 }
180 void Snake::delTail()
181 {
182     SnakeNode *temp=tail;
183     spa->SpaceData[tail->getX()][tail->getY()]=' ';
184     if(tail==head)
185         tail=head=NULL;
186     else
187     {
188         tail=tail->getPrior();
189         tail->setNext(NULL);
190         LEN--;
191     }
192     delete temp;
193 
194 }
195 void Snake::moving()
196 {
197     int a,b;
198     SnakeNode* temp=getHead();
199     a=temp->getX();
200     b=temp->getY();
201     switch(point)
202     {
203     case UP:
204         --a;
205         break;
206     case DOWN:
207         ++a;
208         break;
209     case LEFT:
210         --b;
211         break;
212     case RIGHT:
213         ++b;
214         break;
215     }
216     ///撞墙
217     if(a==SpaceLENG||b==SpaceHIGH||a==-1||b==-1)
218     {
219         FLAG=false;
220     }
221     ///撞自己身体
222     if(spa->SpaceData[a][b]=='*')
223     {
224         spa->SpaceData[a][b]=='@';///用头结点覆盖相撞节点
225         FLAG=false;
226     }
227     ///吃食物
228     if(a==getFx()&&b==getFy())
229     {
230         addHead(a,b);
231         foodCreate();
232     }
233     ///普通移动
234     else
235     {
236         addHead(a,b);
237         delTail();
238     }
239 }
240 void Snake::changePoint(char keydown)///方向控制
241 {
242     switch(keydown)
243     {
244     case 'w':
245     {
246         if(point!=DOWN)
247         {
248             point=UP;
249             break;
250         }
251         else break;
252     }
253     case 'W':
254     {
255         if(point!=DOWN)
256         {
257             point=UP;
258             break;
259         }
260         else break;
261     }
262     case 's':
263     {
264         if(point!=UP)
265         {
266             point=DOWN;
267             break;
268         }
269         else break;
270     }
271     case 'S':
272     {
273         if(point!=UP)
274         {
275             point=DOWN;
276             break;
277         }
278         else break;
279     }
280     case 'a':
281     {
282         if(point!=RIGHT)
283         {
284             point=LEFT;
285             break;
286         }
287         else break;
288     }
289     case 'A':
290     {
291         if(point!=RIGHT)
292         {
293             point=LEFT;
294             break;
295         }
296         else break;
297     }
298     case 'd':
299     {
300         if(point!=LEFT)
301         {
302             point=RIGHT;
303             break;
304         }
305         else break;
306     }
307     case 'D':
308     {
309         if(point!=LEFT)
310         {
311             point=RIGHT;
312             break;
313         }
314         else break;
315     }
316     }
317 }
318 ///----------------------------------------------------
319 ///用户交互界面创建
320 class UserView
321 {
322 public:
323     int menuCreate();
324     int gameSetting();
325 };
326 int UserView::menuCreate()
327 {
328     bool flag=true;
329     while(flag)
330     {
331         cout<<"                 MENU"<<endl<<endl;
332         cout<<"Instruction:"<<endl<<endl;
333         cout<<"The Snake's original length is 3."<<endl<<endl;
334         cout<<"Using 'w,s,a,d' or 'W,S,A,D' to control the direction."<<endl<<endl<<endl<<endl;
335         cout<<"Please Input 'Y'or'y' to start game;"<<endl;
336         cout<<"Please Input 'N'or'n' to end game;"<<endl;
337         cout<<"Please Input 'S'or's' to game setting;"<<endl;
338         cout<<"Please Input else to stay!"<<endl;
339         char startKey=getch();
340         if(startKey=='N'||startKey=='n')
341         {
342             system("cls");
343             cout<<"Good Bye!!!"<<endl;
344             exit(0);
345         }
346         else if(startKey=='Y'||startKey=='y')
347         {
348             system("cls");
349             cout<<"         Game Start!!!"<<endl<<endl<<endl<<endl<<endl;
350             cout<<"         GOOD LUCK!!!"<<endl;
351             getch();
352             flag=false;
353         }
354         else if(startKey=='S'||startKey=='s')
355         {
356             gameSetting();
357         }
358         system("cls");
359     }
360     system("cls");
361     return 0;
362 }
363 int UserView::gameSetting()
364 {
365     system("cls");
366     cout<<"         Setting:"<<endl<<endl<<endl<<endl;
367     cout<<"Please Chose Game Difficulty"<<endl;
368     cout<<"Input 'H'or'h'---Hard  Level"<<endl;
369     cout<<"Input 'N'or'n'---Nomal Level"<<endl;
370     cout<<"Input 'E'or'e'---Easy  Level"<<endl;
371     cout<<"Input else return the MENU"<<endl;
372     char hardKey=getch();
373     if(hardKey=='H'||hardKey=='h')
374     {
375         cout<<"The Game's Difficulty now is Hard  Level!!!"<<endl;
376         speed=HARDSPEED;
377         return 0;
378     }
379     else if(hardKey=='N'||hardKey=='n')
380     {
381         cout<<"The Game's Difficulty now is Nomal  Level!!!"<<endl;
382         speed=NOMALSPEED;
383         return 0;
384     }
385     else if(hardKey=='E'||hardKey=='e')
386     {
387         cout<<"The Game's Difficulty now is Easy  Level!!!"<<endl;
388         speed=EASYSPEED;
389         return 0;
390     }
391     system("cls");
392     return 0;
393 }
394 ///----------------------------------------------------
395 ///程序入口
396 int main()
397 {
398     while(true)
399     {
400         FLAG=true;
401         UserView view;
402         view.menuCreate();
403         spa->InitSpace();
404         Snake sna;
405         sna.foodCreate();
406         spa->DisplaySpace();
407         while(FLAG)
408         {
409             char downKey=getch();
410             sna.changePoint(downKey);
411             ///kbhit(),检查是否有键盘输入,若有,则返回一个非0值,否则返回0,在头文件<conio.h>中定义
412             ///此处FLAG如果不加,会产生蛇吃墙现象
413             while(FLAG&&!kbhit())
414             {
415                 system("cls");
416                 sna.moving();
417                 spa->DisplaySpace();
418                 Sleep(speed);
419             }
420         }
421         cout<<"Game Over!!!"<<endl;
422         cout<<"The Snake's Length is :"<<sna.getLEN()<<endl<<endl<<endl<<endl;
423         cout<<"The Game Will Return Back MENU!"<<endl;
424         getch();
425         system("cls");
426     }
427     return 0;
428 }
View Code

 

 

最后上几张游戏的运行的截图:

 

 

posted @ 2017-01-22 22:11  大大维  阅读(552)  评论(7编辑  收藏  举报