[C++] 贪吃蛇(其中"snake_07.h"是一个自定义的头文件,要求自己把头文件放置) →→→→→进入此内容的聊天室

来自 , 2019-09-21, 写在 C++, 查看 126 次.
URL http://www.code666.cn/view/405e2890
  1. #include "stdio.h"
  2. #include "stdlib.h"
  3. #include "graphics.h"
  4. #include "conio.h"
  5. #include "bios.h"
  6. #include "time.h"
  7. #include "dos.h"
  8. #include "string.h"
  9. #include "snake_07.h"
  10.  
  11. struct snake{
  12.         int x[snake_node];// 蛇每一节的左上角x坐标
  13.         int y[snake_node];// 蛇每一节的左上角y坐标
  14.         int node; // 蛇当前有多少节,初始化为2
  15.         int direction;// 蛇移动的方向,初始化为DIRECTION_RIGHT
  16.         int life;// 蛇的生命值
  17.         int foodCount; // 蛇吃了多少食物,初始为0
  18.         int score; // 得分,初始为0
  19. } snake;
  20.  
  21. struct food{
  22.         int x;// 食物的左上角的x坐标
  23.         int y;// 食物的左上角的y坐标
  24. } food;
  25. void init();
  26. void close();
  27.  
  28. void startCanvas();
  29. void playCanvas(int mission);
  30. void play(int wallMission, int barreriMission, int speed, char title[],int snakeX,int snakeY);
  31.  
  32. void initFood();
  33. void drawFood();
  34. void initSnake(int x,int y);
  35. void drawSnake();
  36. void snakeMove(int key);
  37. int needToMove(int key);
  38. int isDirectionKey(int key);
  39.  
  40. void initHorizontalWall(int mission);
  41. void initVerticalWall(int mission);
  42. void initBarriers(int mission);
  43. void drawWallAndBarrier(int wallMission, int barrierMission);
  44.  
  45. int collision();
  46. void bitFood();
  47. int bitSelf();
  48.  
  49. void printScore();
  50. void gameOver();
  51. void ccl();
  52.  
  53. int round(int o);
  54. int getX(int col);
  55. int getY(int row);
  56. int getRow(int y);
  57. int getCol(int x);
  58.  
  59. int main()
  60. {
  61.     init();
  62.     startCanvas();
  63.     close();
  64.     return 0;
  65. }
  66. void init(){
  67.         int gdriver=DETECT,gmode;
  68.         registerbgidriver(EGAVGA_driver);
  69.     initgraph(&gdriver,&gmode,"");
  70. }
  71. void close(){
  72.         getch();
  73.         closegraph();
  74. }
  75. /**
  76.         游戏开始界面,提供相应的选项,如模式选择,关卡选择,及退出
  77. */
  78. void startCanvas(){
  79.         int key;
  80.         cleardevice();
  81.         setbkcolor(9);
  82.         setcolor(14);
  83.         settextstyle(0,0,3);
  84.         outtextxy(20,20,"Welcome to My Snake Game!");
  85.         settextstyle(0,0,2);
  86.         outtextxy(200,130,"1. Mission One");   
  87.         outtextxy(200,160,"2. Mission Two");
  88.         outtextxy(200,190,"3. Mission Three");
  89.         outtextxy(200,220,"4. Quit");
  90.         key=bioskey(0);
  91.         switch(key){
  92.                 case key_one:playCanvas(key_one);break;
  93.                 case key_two:playCanvas(key_two);break;
  94.                 case key_three:playCanvas(key_three);break;
  95.                 case key_four:cleardevice(); exit(0);break;
  96.         }
  97. }
  98. /**
  99.         进入指定模式或关卡的游戏界面
  100. */
  101. void playCanvas(int mission){
  102.         cleardevice();
  103.         if(mission==key_one){
  104.                 play(WALL_MISSION_ONE,BARRIER_MISSION_ONE,SPEED_MISSION_ONE,"Mission:1",30,60);
  105.         }else if(mission==key_two){
  106.                 play(WALL_MISSION_TWO,BARRIER_MISSION_TWO,SPEED_MISSION_TWO,"Mission:2",30,60);
  107.         }else if(mission==key_three){
  108.                 play(WALL_MISSION_THREE,BARRIER_MISSION_THREE,SPEED_MISSION_THREE,"Minssion:3",30,60);
  109.         }
  110. }
  111. void play(int wallMission,int barrierMission,int speed,char title[],int snakeX,int snakeY)
  112. {
  113.         int key=key_right;
  114.         int isRunning=1;
  115.         ccl();
  116.         outtextxy(20,20,title);
  117.         initHorizontalWall(wallMission);
  118.         initVerticalWall(wallMission);
  119.         initBarriers(barrierMission);
  120.         initFood(); // 出现随机食物
  121.         initSnake(snakeX, snakeY); //出现一条随机的蛇
  122.         printScore();   // 开始判断用户的键盘输入
  123.         while(snake.life){
  124.                 while(!kbhit()){
  125.                         snakeMove(key); //让蛇移动
  126.                         drawFood();// 重新绘制食物
  127.                         drawWallAndBarrier(wallMission, barrierMission);//绘制围墙和障碍物
  128.                         if(collision()){ //进行碰撞检测 ,如果有碰撞,则游戏结束
  129.                                 if(--snake.life==0){
  130.                                         isRunning=0;
  131.                                         break;
  132.                                 }
  133.                         }
  134.                         bitFood(); //检测吃食物
  135.                         delay(speed);// 延迟5指定毫秒数
  136.                 }
  137.                 if(!isRunning){
  138.                         break;
  139.                 }
  140.                 //接收用户的键盘输入,如果按的方向键,则让蛇在该方向上移动,如果按的esc键,则退出到选择界面
  141.                 key=bioskey(0);
  142.                 if(isDirectionKey(key)){
  143.                         if(needToMove(key)){// 判断蛇是否需要更换方向
  144.                                 snakeMove(key);
  145.                         }
  146.                 } else if(key==key_esc){
  147.                         startCanvas();
  148.                 }else if(key==key_a){
  149.                         getch();
  150.                 }
  151.         }
  152.         gameOver();    
  153. }
  154. /**
  155.         根据围墙数组和关卡初始化该关的横向围墙
  156. */
  157. void initHorizontalWall(int mission){
  158.         int i;
  159.         for(i=0;i<TOTAL_COLS;i++){
  160.                 canvas[0][i]=HORIZONTAL_WALL[mission-1][i];
  161.                 canvas[TOTAL_ROWS-1][i]=HORIZONTAL_WALL[mission][i];
  162.         }
  163. }
  164. /**
  165.         通过列索引获取该格子的x坐标
  166. */
  167. int getX(int col){
  168.         return col*rectangle_size+canvas_min_x;
  169. }
  170. /**
  171.         通过行索引获取该格子的y坐标
  172. */
  173. int getY(int row){
  174.         return row*rectangle_size+canvas_min_y;
  175. }
  176. /**
  177.         根据围墙数组和关卡初始化该关的纵向围墙
  178. */
  179. void initVerticalWall(int mission){
  180.         int i;
  181.         for(i=0;i<TOTAL_ROWS;i++){
  182.                 canvas[i][0]=VERTICAL_WALL[mission-1][i];
  183.                 canvas[i][TOTAL_COLS-1]=VERTICAL_WALL[mission][i];
  184.         }
  185. }
  186.  
  187. void initBarriers(int mission){
  188.         int i;
  189.         int type;
  190.         for(i=0;i<TOTAL_BARRIERS;i++){
  191.                 type=barriers[mission][i].type;
  192.                 if(type==EMPTY){ // 去除掉barriers后面的那些未被赋值的障碍物
  193.                         break;
  194.                 }
  195.                 canvas[barriers[mission][i].row][barriers[mission][i].col]=barriers[mission][i].type;
  196.         }
  197. }
  198. /**
  199.         根据初始化的围墙数据绘制围墙
  200. */
  201. void drawWallAndBarrier(int , int ){
  202.         int i,j;
  203.         for(i=0;i<TOTAL_ROWS;i++){
  204.                 for(j=0;j<TOTAL_COLS;j++){
  205.                         if(canvas[i][j]==WALL){
  206.                                 setfillstyle(8,10);
  207.                                 bar(getX(j),getY(i), getX(j)+rectangle_size,getY(i)+rectangle_size);
  208.                         } else if(canvas[i][j]==BARRIER_RECT){
  209.                                 setfillstyle(8,12);
  210.                                 bar(getX(j),getY(i), getX(j)+rectangle_size,getY(i)+rectangle_size);
  211.                         } else if(canvas[i][j]==BARRIER_CIRCLE){
  212.                                 circle(getX(j)+rectangle_size/2, getY(i)+rectangle_size/2,rectangle_size/2);
  213.                         }
  214.                 }
  215.         }
  216. }
  217. /**
  218.         在有效区域内随机产生食物,保留坐标,并且确保食物与方格重合
  219. */
  220. void initFood(){
  221.         int row,col;
  222.         randomize();
  223.         food.x=rand()%(canvas_valid_max_x-canvas_valid_min_x-2*rectangle_size)+canvas_valid_min_x;
  224.         food.y=rand()%(canvas_valid_max_y-canvas_valid_min_y-2*rectangle_size)+canvas_valid_min_y;
  225.         food.x=round(food.x);
  226.         food.y=round(food.y);
  227.         row=getRow(food.y);
  228.         col=getCol(food.x);
  229.         // 判断食物是否出现在障碍物上,如果在障碍物上,重新获取食物
  230.         while(canvas[row][col]==BARRIER_RECT||canvas[row][col]==BARRIER_CIRCLE){
  231.                 if(food.x==canvas_valid_max_x-rectangle_size){
  232.                         food.x=canvas_valid_min_x;
  233.                 }
  234.                 if(food.y==canvas_valid_max_y-rectangle_size){
  235.                         food.y=canvas_valid_min_y;
  236.                 }
  237.                 food.x+=rectangle_size;
  238.                 food.y+=rectangle_size;
  239.                 row=getRow(food.y);
  240.                 col=getCol(food.x);
  241.         }
  242. }
  243. /**
  244.         对整数o进行四舍五入取整操作
  245. */
  246. int round(int o){
  247.         return(int)((o+5)/10.f)*10;
  248. }
  249. /**
  250.         根据随机产生的食物坐标绘制食物
  251. */
  252. void drawFood(){
  253.         setfillstyle(1,GREEN);
  254.         bar(food.x,food.y,food.x+rectangle_size,food.y+rectangle_size);
  255. }
  256. /**
  257.         在有效区域内随机产生一条蛇并保留坐标,并且确保蛇头与某个方格重合,方向初始化为向右,蛇身2节
  258. */
  259. void initSnake(int x,int y){
  260.         snake.node=2;
  261.         snake.life=1;          
  262.         snake.foodCount=0;
  263.         snake.score=0;
  264.         snake.direction=direction_right;
  265.         snake.x[0]=x;
  266.         snake.y[0]=y;
  267. }
  268. /**
  269.         根据随机产生的蛇的坐标绘制蛇
  270. */
  271. void drawSnake(){
  272.         int i;
  273.         for(i=0;i<snake.node;i++){
  274.                 rectangle(snake.x[i],snake.y[i],snake.x[i]+rectangle_size,snake.y[i]+rectangle_size);
  275.         }
  276. }
  277. /**
  278.         根据指定的方向让蛇在该方向上移动。
  279.         1、需要擦除蛇身的最后一节,先保留住最后一节的x和y坐标,最后使用与背景色相同的颜色重新画最后一节
  280.         2、让蛇移动起来,相当于把蛇前面的坐标赋值给蛇后面节点,最后整条蛇重新绘制出来
  281. */
  282. void snakeMove(int key){
  283.         int i;
  284.         int x=snake.x[snake.node-1];
  285.         int y=snake.y[snake.node-1];
  286.         for(i=snake.node-1;i>0;i--){
  287.                 snake.x[i]=snake.x[i-1];
  288.                 snake.y[i]=snake.y[i-1];
  289.         }
  290.         if(key==key_up&&(snake.direction==direction_left||snake.direction==direction_right)){
  291.                 snake.direction=direction_up;
  292.         }else if(key==key_down&&(snake.direction==direction_left||snake.direction==direction_right)){
  293.                 snake.direction=direction_down;
  294.         }else if(key==key_left&&(snake.direction==direction_down||snake.direction==direction_up)){
  295.                 snake.direction=direction_left;
  296.         }else if(key==key_right&&(snake.direction==direction_up||snake.direction==direction_down)){
  297.                 snake.direction=direction_right;
  298.         }
  299.         if(snake.direction==direction_up){
  300.                 snake.y[0]-=rectangle_size;
  301.         }else if(snake.direction==direction_down){
  302.                 snake.y[0]+=rectangle_size;
  303.         }else if(snake.direction==direction_left){
  304.                 snake.x[0]-=rectangle_size;
  305.         }else if(snake.direction==direction_right){
  306.                 snake.x[0]+=rectangle_size;
  307.         }
  308.         setcolor(9);
  309.         rectangle(x, y,x+rectangle_size,y+rectangle_size);
  310.         setcolor(14);
  311.         drawSnake();
  312. }
  313. /**
  314.         判断用户按键后,是否需要把蛇换个方向
  315. */
  316. int needToMove(int key){
  317.         if(snake.direction==key||
  318.         (snake.direction==direction_up&&key==direction_down)||
  319.         (snake.direction==direction_down&&key==direction_up)||
  320.         (snake.direction==direction_left&&key==direction_right)||
  321.         (snake.direction==direction_right&&key==direction_left)){
  322.                 return 0;
  323.         }
  324.         return 1;
  325. }
  326. /**
  327.         判断用户是否按的方向键
  328. */
  329. int isDirectionKey(int key){
  330.         return (key==key_up||key==key_down||key==key_left||key==key_right)?1:0;
  331. }
  332. /**
  333.         判断是否碰撞围墙,障碍物,蛇身,如果碰撞,则返回1
  334. */
  335. int collision(){
  336.         int snakeRow=getRow(snake.y[0]);
  337.         int snakeCol=getCol(snake.x[0]);
  338.         int snakeRow1=getRow(snake.y[1]);
  339.         int snakeCol1=getCol(snake.x[1]);
  340.         if((canvas[snakeRow][snakeCol]==WALL||canvas[snakeRow1][snakeCol1]==WALL)||
  341.                 (canvas[snakeRow][snakeCol]==BARRIER_RECT||canvas[snakeRow1][snakeCol1]==BARRIER_RECT)||
  342.                 (canvas[snakeRow][snakeCol]==BARRIER_CIRCLE||canvas[snakeRow1][snakeCol1]==BARRIER_CIRCLE)||bitSelf()){
  343.                 return 1;
  344.         }
  345.         return 0;
  346. }
  347. /**
  348.         通过y坐标获取该格子的行索引
  349. */
  350. int getRow(int y){
  351.         return(y-canvas_min_y)/10;
  352. }
  353. /**
  354.         通过x坐标获取该格子的列索引
  355. */
  356. int getCol(int x){
  357.         return(x-canvas_min_x)/10;
  358. }
  359. /**
  360.         吃到食物,蛇身变长,分数增加,重新出现食物
  361. */
  362. void bitFood(){
  363.         int foodRow=getRow(food.y);
  364.         int foodCol=getCol(food.x);
  365.         int snakeRow=getRow(snake.y[0]);
  366.         int snakeCol=getCol(snake.x[0]);
  367.         int snakeRow1=getRow(snake.y[1]);
  368.         int snakeCol1=getCol(snake.x[1]);
  369.         if(foodRow==snakeRow&&foodCol==snakeCol||foodRow==snakeRow1&&foodCol==snakeCol1){
  370.                 snake.score+=10;
  371.                 setfillstyle(1,9);
  372.                 bar(food.x,food.y,food.x+rectangle_size,food.y+rectangle_size);
  373.                 initFood();
  374.                 snake.x[snake.node]=snake.x[snake.node-1];
  375.                 snake.y[snake.node]=snake.y[snake.node-1];
  376.                 snake.node+=1;
  377.                 printScore();
  378.         }
  379. }
  380. /**
  381.         判断是否碰撞蛇本身
  382. */
  383. int bitSelf(){
  384.         int i;
  385.         if(snake.node<5){
  386.                 return 0;
  387.         }
  388.         for(i=5;i<snake.node;i++){
  389.                 if(snake.x[0]==snake.x[i]&&snake.y[0]==snake.y[i]){
  390.                         return 1;
  391.                 }
  392.         }
  393.         return 0;
  394. }
  395. /**
  396.         在游戏界面打印分数
  397. */
  398. void printScore(){
  399.         char score[20];
  400.         setcolor(9);
  401.         outtextxy(400,20,lastScore);
  402.         sprintf(score,"Score: %d",snake.score);
  403.         strcpy(lastScore,score);
  404.         setcolor(14);
  405.         outtextxy(400,20,score);
  406. }
  407. void gameOver(){
  408.         cleardevice();
  409.         settextstyle(0,0,4);
  410.         outtextxy(150,150,"Game Over!");
  411.         outtextxy(180,250,lastScore);
  412. }
  413. /**
  414.         显示游戏结束画面
  415. */
  416. void ccl(){
  417.         int i,j;
  418.         for(i=0;i<TOTAL_ROWS;i++){
  419.                 for(j=0;j<TOTAL_COLS;j++){
  420.                         canvas[i][j]=EMPTY;
  421.                 }
  422.         }
  423.         cleardevice();
  424. }

回复 "贪吃蛇(其中"snake_07.h"是一个自定义的头文件,要求自己把头文件放置)"

这儿你可以回复上面这条便签

captcha