贪吃蛇游戏构建

 

使用的编译器:DEV C++,VS code

编译语言:C语言,JavaScript

 

 在知乎上看到的 RxJS 游戏之贪吃蛇,感觉很有趣,想自己动手试试。

 

1. github上的源码 VS code的调试并不简单,会出现如下错误:

(1)无法在PATH中找到node

百度后的解决方案为:在node官网下载好nodejs,利用cmd命令处理程序验证环境变量Path中是否加入了nodejs的路径。

具体方案参照:VS code调试nodejs,无法在PATH上找到运行时的node

(2)找不到rxjs后续文件

2.多次JavaScrip尝试无果后想试试C语言实现。

转战DEV C++,用C语言实现起来还是挺简单的,难点在于:

(1)输入为键盘的“上”“下”“左”“右”键,可通过switch语句来完成控制。

(2)蛇的结构体定义初始化,游戏窗口设置,显示屏句柄变量定义需要扎实的C语言功底的。

(3)蛇的移动控制,蛇和菜单的打印,蛇吃食物后的加速控制等。

参考:C语言之贪吃蛇游戏源码

 

下面附上C语言代码,可以自己试试:

/**************************************************************************************************************
 **编写者:huangminqiang
 **编写日期:2010年9月8号
 **简要描述:贪吃蛇游戏,可加速,有颜色变化。
 **注:在DEV C++环境下能正常运行,印象中加速不太理想,敲键盘if(kbhit)可改为while(kbhit)。
 **************************************************************************************************************/

  1 #include <stdio.h>
  2 #include <windows.h>
  3 #include <conio.h>
  4 #include <time.h>
  5 //游戏窗口
  6 #define FrameX 4   //游戏窗口左上角的X轴坐标
  7 #define FrameY 4   //游戏窗口左上角的Y轴坐标
  8 #define Frame_height  20 //游戏窗口的高度
  9 #define Frame_width   20 //游戏窗口的宽度
 10 //定义全局变量
 11 int i,j;
 12 int a[2];     //用于记住蛇尾坐标,其中a[0]、a[1]分别表示横、竖坐标
 13 //声明蛇的结构体
 14 struct Snake
 15 {
 16  int x[100];    //蛇的横坐标,其中x[0]表示蛇尾的横坐标,x[N-1]表示蛇头的横坐标
 17  int y[100];    //蛇的竖坐标,其中y[0]表示蛇尾的竖坐标,y[N-1]表示蛇头的竖坐标
 18  int count;    //蛇吃食物的个数
 19  int length;    //蛇的长度
 20  int speed;    //蛇的速度
 21 };
 22 //声明食物的结构体
 23 struct Food
 24 {
 25  int x;     //食物的横坐标
 26  int y;     //食物的竖坐标
 27 };
 28  
 29 void start_game();
 30 void over_game();
 31 int main()
 32 {
 33  system("color 0D");  //设置文本为粉红色
 34  start_game();   //开始游戏
 35  over_game();   //结束游戏
 36 }
 37 /******光标移到指定位置**************************************************************/
 38 void gotoxy(HANDLE hOut, int x, int y)
 39 {
 40  COORD pos;
 41  pos.X = x;  //横坐标
 42  pos.Y = y;  //纵坐标
 43  SetConsoleCursorPosition(hOut, pos);
 44 }
 45 /******设置文本为绿色*****************************************************************/
 46 void Set_TextColor_Green (void)
 47 { 
 48  HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE);
 49  
 50  SetConsoleTextAttribute(Handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
 51 }
 52 /******制作游戏窗口******************************************************************/
 53 void make_frame()
 54 {
 55  HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);  //定义显示器句柄变量
 56  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+13);  //打印选择菜单
 57  printf("Esc 退出游戏");
 58  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+15);
 59  printf("长按方向键:加速");
 60  gotoxy(hOut,FrameX,FrameY);       //打印框角
 61  printf("");
 62  gotoxy(hOut,FrameX+2*Frame_width-2,FrameY);
 63  printf("");
 64  gotoxy(hOut,FrameX,FrameY+Frame_height);
 65  printf("");
 66  gotoxy(hOut,FrameX+2*Frame_width-2,FrameY+Frame_height);
 67  printf("");
 68  for(i=2;i<2*Frame_width-2;i+=2)
 69  {
 70   gotoxy(hOut,FrameX+i,FrameY);
 71   printf("");         //打印上横框
 72  }
 73  for(i=2;i<2*Frame_width-2;i+=2)
 74  {
 75   gotoxy(hOut,FrameX+i,FrameY+Frame_height);
 76   printf("");         //打印下横框
 77  }
 78  for(i=1;i<Frame_height;i++)
 79  {
 80   gotoxy(hOut,FrameX,FrameY+i); 
 81   printf("");         //打印左竖框
 82  }
 83  for(i=1;i<Frame_height;i++)
 84  {
 85   gotoxy(hOut,FrameX+2*Frame_width-2,FrameY+i); 
 86   printf("");         //打印右竖框
 87  }
 88  gotoxy(hOut,FrameX+Frame_width-5,FrameY-2);   //打印游戏名称 
 89  Set_TextColor_Green ();        //设置蛇为绿色
 90  printf("贪吃蛇游戏");
 91 }
 92 /******结束菜单*******************************************************************/
 93 void over_game()
 94 {
 95  system("cls");
 96  printf("\n\n\n\n\n\n\n\n\t\t\t\t游戏结束\n\n\n");
 97  Sleep(2000);
 98  getch();
 99 }
100 /******菜单信息***************************************************************/
101 void print_information(HANDLE hOut,struct Snake *snake,struct Food *food)
102 {
103  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+1);
104  printf("level : %d",snake->count/5+1);    //打印游戏等级
105  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+3);
106  printf("score : %d",10*snake->count);    //打印游戏得分
107  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+5);
108  printf("eat food : %d",snake->count);    //打印产生食物个数 
109  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+7);
110  printf("speed : %dms",snake->speed);    //打印游戏速度
111  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+9);
112  printf("foodX : %d",food->x);      //打印食物的横坐标
113  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+11);
114  printf("foodY : %d",food->y);      //打印食物的竖坐标
115 }
116 /******初始化蛇**********************************************************************/
117 void init_snake(struct Snake *snake)
118 {
119  snake->x[0]=FrameX+2;     //初始化蛇的横坐标 
120  snake->y[0]=FrameY+Frame_height/2;  //初始化蛇的竖坐标 
121  snake->speed=300;      //初始化蛇的速度为300ms
122  snake->length=3;      //初始化蛇的长度为3节
123  snake->count=0;       //初始化蛇吃的个数为0
124  for(i=1;i<snake->length;i++)
125  {/* 依次得到蛇身、蛇头的坐标 */
126   snake->x[i]=snake->x[i-1]+2;
127   snake->y[i]=snake->y[i-1];
128  } 
129 }
130 /******移动蛇*************************************************************************/
131 void move_snake(HANDLE hOut,struct Snake *snake)
132 {
133  gotoxy(hOut,snake->x[0],snake->y[0]);
134  printf("  ");       /* 清除蛇尾*/
135  for(i=1;i<snake->length;i++)
136  {/* 后一节的坐标依次取代前一节的坐标 */
137   snake->x[i-1]=snake->x[i];
138   snake->y[i-1]=snake->y[i];
139  }
140 }
141 /******打印蛇*************************************************************************/
142 void print_snake(HANDLE hOut,struct Snake *snake)
143 {
144  for(i=0;i<snake->length;i++)
145  {
146   gotoxy(hOut,snake->x[i],snake->y[i]);
147   if(i==0)
148   {
149    printf("");       //打印蛇尾
150   }
151   else if(i==snake->length-1)
152   {
153    printf("¤");       //打印蛇头
154   }
155   else
156   {
157    printf("");       //打印蛇身
158   }
159  }
160 }
161 /******随机产生食物*******************************************************************/
162 void get_food(HANDLE hOut,struct Snake *snake,struct Food *food)
163 {
164  srand((unsigned)time(NULL));       //初始化随机数
165  while(1)
166  {/* 产生食物的条件:1.在游戏窗口内 2.不在蛇的身上 */ 
167   food->x = rand() % (Frame_width-1);
168   food->y = rand() % Frame_height;
169   if( food->x==0 || food->y==0 )
170   {
171    continue;
172   }
173   food->x = 2*food->x + FrameX;      //得到食物的横坐标
174   food->y+=FrameY;         //得到食物的竖坐标
175   for(i=0;i<snake->length;i++)
176   {/* 判断食物是否在蛇的身上,如果在蛇身上,则重新产生;否则,打印蛇身 */
177    if( food->x==snake->x[i] && food->y==snake->y[i] )
178    {
179     break;
180    }
181   }
182   if(i==snake->length)
183   {
184    gotoxy(hOut,food->x,food->y);
185    printf("");
186    break;
187   } 
188  }
189 }
190 /******吃食物***************************************************************************/
191 void eat_food(HANDLE hOut,struct Snake *snake,struct Food *food)
192 {
193  if( snake->x[snake->length-1]==food->x && snake->y[snake->length-1]==food->y )
194  {/* 如果蛇头位置与食物位置相同,吃食物 */
195   snake->length++;      //吃一个食物,蛇身增长一节
196   for(i=snake->length-1;i>=1;i--)
197   {/* 蛇后节坐标依次赋值给蛇前一节的坐标,依次得到蛇身及蛇头的坐标 */
198    snake->x[i]=snake->x[i-1];
199    snake->y[i]=snake->y[i-1];
200   } 
201   snake->x[0]=a[0];      //得到蛇尾移动前的横坐标
202   snake->y[0]=a[1];      //得到蛇尾移动前的竖坐标  
203   get_food(hOut,snake,food);    //重新产生食物
204   snake->count++;       //食物的个数增1
205   if( snake->count%5==0 )
206   {/* 当蛇吃Up_level个食物时,速度加快Up_speed毫秒并且升一级 */
207    snake->speed-=50;
208   }
209  }
210 }
211 /******穿墙**********************************************************************************/
212 void through_wall(HANDLE hOut,struct Snake *snake,char ch)
213 {
214  if( ch==72 && snake->y[snake->length-1]==FrameY)
215  {
216   snake->y[snake->length-1] = FrameY+Frame_height-1; //如果蛇在上框且向上移动,穿墙
217  }
218  if( ch==80 && snake->y[snake->length-1]==FrameY+Frame_height )
219  {
220   snake->y[snake->length-1] = FrameY+1;    //如果蛇在下框且向下移动,穿墙
221  }
222  if( ch==75 && snake->x[snake->length-1]==FrameX )
223  {
224   snake->x[snake->length-1] = FrameX+2*Frame_width-4; //如果蛇在左框且向左移动,穿墙
225  }
226  if( ch==77 && snake->x[snake->length-1]==FrameX+2*Frame_width-2 )
227  {
228   snake->x[snake->length-1] = FrameX+2;    //如果蛇在右框且向右移动,穿墙
229  }
230 }
231 /******判断蛇是否死**************************************************************************/
232 int if_die(struct Snake *snake)
233 {/* 当蛇头碰到自身时,蛇死 ,返回值为0 */
234  for(i=0;i<snake->length-1;i++)
235  {
236   if( snake->x[snake->length-1]==snake->x[i] && snake->y[snake->length-1]==snake->y[i] )
237   {
238    return 0;
239   }
240  }
241  return 1;
242 }
243 /******开始游戏*******************************************************************************/
244 void start_game()
245 {
246  unsigned char ch=77;        //定义用于接收键盘输入的字符变量
247  HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); //定义显示器句柄变量
248  struct Snake s,*snake=&s;      //定义蛇的结构体指针并指向蛇的结构体
249  struct Food f,*food=&f;       //定义食物的结构体指针并指向食物的结构体
250  
251  make_frame();         //制作游戏窗口 
252  init_snake(snake);        //初始化蛇
253  get_food(hOut,snake,food);      //随机产生食物
254  while(1)
255  {
256   print_information(hOut,snake,food);   //打印菜单信息
257   a[0]=snake->x[0];       //记住蛇尾的横坐标
258   a[1]=snake->y[0];       //记住蛇尾的竖坐标
259   j=0;
260   if(kbhit())
261   {/* 判断是否按下键盘,如果按下,ch接收键盘输入 */
262    ch=getch();
263    if(kbhit())
264    {/* 如果长按键盘,则加速 */
265     Sleep(20);
266     j=1;
267    }
268   }
269   switch(ch)
270   {
271    case 72:
272     {/* 向上移动 */
273      move_snake(hOut,snake);   //移动蛇
274      snake->y[snake->length-1]-=1; //蛇头的竖坐标向上移,即减1 
275      break;
276     }
277    case 80:
278     {/* 向下移动 */
279      move_snake(hOut,snake);   //移动蛇
280      snake->y[snake->length-1]+=1; //蛇头的竖坐标向下移,即加1
281      break;
282     }
283    case 75:
284     {/* 向左移动 */
285      move_snake(hOut,snake);   //移动蛇
286      snake->x[snake->length-1]-=2; //蛇头的横坐标向左移,即减2
287      break;
288     }    
289    case 77:
290     {/* 向右移动 */
291      move_snake(hOut,snake);   //移动蛇
292      snake->x[snake->length-1]+=2; //蛇头的横坐标向右移,即加2
293      break;
294     }
295   }
296   through_wall(hOut,snake,ch);    //穿墙   
297   eat_food(hOut,snake,food);     //吃食物
298   print_snake(hOut,snake);     //打印蛇
299   if( if_die(snake)==0 || ch==27 || snake->speed==50 )
300   {/* 游戏结束条件:1.蛇碰到自身 2.按Esc键 3.速度为50ms */
301    gotoxy(hOut,FrameX+Frame_width-2,FrameY+Frame_height/2-1);
302    printf("Game Over");
303    Sleep(2000);
304    break;
305   }
306   if(j==0)
307   {
308    Sleep(snake->speed);      //延迟时间
309   }
310   else
311   {
312    Sleep(10);
313   } 
314  }
315 }

 运行结果:

 

3.还会努力尝试用VS Code编译器来实现,在这之前先把编译器使用熟练,会编译运行,了解它的操作。

posted @ 2018-04-19 15:44  BoBoRing  阅读(823)  评论(0编辑  收藏  举报