贪吃蛇游戏构建
使用的编译器: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编译器来实现,在这之前先把编译器使用熟练,会编译运行,了解它的操作。