• C语言版flappy bird黑白框游戏



          在此记录下本人在大一暑假,2014.6~8这段时间复习C语言,随手编的一个模仿之前很火热的小游戏----flappy bird。代码bug基本被我找光了,如果有哪位兄弟找到其他的就帮我留言下吧,谢谢了!

          代码的完美度肯定是不够的,随手编的嘛,找完bug后就没再去想怎样优化它了,毕竟时间有限。


         先说下它的设计思路吧,算法方面,基本是纯靠for if 语句加上纯粹的坐标x,y运算实现的,在下面的代码里,将会看到很多阿拉伯数字的加加减减。没有用到链表什么的,当然,我相信,如果用到链表的话,会更简单,代码量更少。引用到的函数库有四个:

    1 #include<stdio.h>
    2 #include<Windows.h>//win
    3 #include <time.h> 
    4 #include<stdlib.h>

    宏定义 :define一些标识图形,p为烟囱的组成单位方块,“ “为消除方块时用到的输出空白,-是界面美化,”鸟“是游戏体

    1 #define P printf("■")
    2 #define PR printf(" ")
    3 #define Q printf("-")
    4 #define Br printf("鸟")

    定义结构体,就一个鸟的结构体,以及一条最重要的函数----句柄的初始化。

     1 typedef    struct brid
     2 {
     3     double x,y;
     4     int score;//分数
     5 };
     6 /*typedef struct Fangkuai
     7 {
     8     double x,y;
     9 };*/ //此结构体废除
    10 void Position(double x, double y) {//光标(坐标)函数
    11     COORD pos = {
    12         x - 1, y - 1
    13     };
    14     HANDLE Out = GetStdHandle(STD_OUTPUT_HANDLE);//创建句柄
    15     SetConsoleCursorPosition(Out, pos);//将句柄指向坐标,变为坐标句柄
    16 }

    下面是一些辅助函数,加上注释,这里再作介绍。由于函数名字基本是中文字的评语,这个之所以这样做,还是上面的原因,想改,可以自己改。

       jiemian(),这个函数的作用的在特定的位置输出”--------“,美化界面用的,置于为什么for循环里面我设置的i<103呢,是因为控制台的宽度大概是103像素,所以,
    设置每一像素输出一个Q 即 - ,Position函数就是把特定此时的坐标;

    jiemian1(),不作解释,相信看得明白;

    feixing(...)鸟的飞行函数,思想很简单,先选择好一个坐标位置,显示出鸟,再停顿一段时间在相同的位置输出空白,达到非按键up操作时的下降目的;

    fenshuYUnandu(...),分数函数,显示分数;

    check1(...),检查烟囱外是否撞墙函数,这里要仔细看了,否则你会很难读懂!d 数组分别存储两烟囱之间的间距15~16像素, e 数组用来存储每条烟囱移动到与鸟的x坐标相同时的固定距离,i数组是传进来的烟囱移动的坐标变化,e-i-t是用来判断烟囱移动的时候,何时与鸟x相同,到这里,可能你有疑问了,为什么不直接判断烟囱的x和鸟的x重合,因为烟囱是动态的,同时它们还有距离限制,如果不加以限制就会乱,烟囱不是一条在往左边移动,是5条,0~4,如果相等,进入第一个if语句,进行第二次判断,判断此时鸟的y坐标是否是烟筒的入口y,如果是,则不报错,如果不是,证明撞墙了,最后的一个if语句是判断上下边界的撞墙;

    check(...),烟囱入口撞墙判断,这条较上条较复杂,因为烟囱的入口是有两列像素方块组成的,就是说,判断的时候要判断两列的方块。模仿上面,b c 数组分别是左列和右列的烟囱间距值,剩下的步骤就是判断入口内鸟的x是否与烟囱的x相同;

    下面的一条最重要的函数,烟囱的制造、移动函数。
      1 void jiemian()//界面函数
      2 {
      3     int i=23;
      4     for(;i<103;i++)
      5     {
      6         Position(i-22,1.5);//上边
      7         Q;
      8     }
      9     if(i==103)
     10     {
     11         for(i=23;i<103;i++)
     12         {
     13             Position(i-22,24);//下边
     14             Q;
     15         }
     16     }
     17 }
     18 void jiemian1() {
     19     printf("____________________________________________________________________________
    ");
     20     printf("");
     21     printf("");
     22     printf(" ■C语言非链表版:Flappy Bird
    ");
     23     printf(" ■编写人:LinGuanH
    ");
     24     printf(" ■日期:2014.7.30
    ");
     25     printf(" ■耗时:4小时37分
    ");
     26     printf(" ■游戏说明:
    ");
     27     printf(" ■1-按键盘中的上箭头使鸟起飞
    ");
     28     printf(" ■2-分数每过20,难度增大,烟囱入口减小!
    ");
     29     printf(" ■3-光标显示方式为中文鸟字
    ");
     30     printf(" ■4-介于VS中graphics.h函数库使用失败,导致原图插入不了,所用转用黑白框。
    ");
     31     printf(" ■5-撞墙失败,游戏会提示输了,但是不会return 0,你可以继续按方向键接着玩。
    ");
     32     printf("");
     33     printf("");
     34     printf("");
     35     printf(" ■代码内带有注释,感兴趣的可以直接修改,增加其他效果
    ");
     36     printf(" ■必然存在bug,找到了麻烦跟我说声,谢谢。
    ");
     37     printf(" ■请按键盘的任意一个键继续。
    ");
     38     printf("");
     39     printf("");
     40     printf("");
     41     printf(" ____________________________________________________________________________
    ");
     42     system("pause");
     43 }
     44 /*void cleanjudge(int i)
     45 {
     46     if(i==77)
     47         {
     48             for(int i=1;i<6;i++)
     49             {
     50                 Position(2,i);
     51                 PR;
     52                 Position(4,i);
     53                 PR;
     54             }
     55         }
     56 }*/ //清屏函数作废
     57 void feixing(brid B,int y)//鸟飞行坐标函数
     58 {                        
     59         Position(B.x,B.y);Br;//创建鸟
     60         Sleep(200);//停顿0.2秒再下掉,也是难度的改变方法。
     61         Position(B.x,B.y);PR;//清除鸟
     62             //return 0;        
     63 }
     64 void fenshuYUnandu(brid B,int i[],int o[])//显示分数函数
     65 {
     66     Position(38,25);//固定分数显示位置
     67     printf("分数为:%d",B.score);
     68         
     69 }
     70 void check(brid B,int i[],int o[],int temp)//检查非入口撞墙函数
     71 {
     72     int t,d[5],e[5];
     73     d[0]=0;d[1]=16;d[2]=31;d[3]=46,d[4]=61;
     74     e[0]=78;e[1]=77;e[2]=77;e[3]=77;e[4]=77;
     75     for(t=0;t<=4;t++)
     76     {
     77         if(B.x==e[t]-i[t]+d[t]){
     78             if(B.y<=o[t]+6-temp||B.y>=o[t]+temp-1){
     79                 Position(B.x,B.y);Br;printf("
    ");Position(B.x,B.y+1);
     80                 printf("Lost the game!
    ");system("pause");
     81           }
     82        }    
     83     if(B.y>=24||B.y<=1.5){
     84                 printf("Lost the game!
    ");system("pause");
     85        }
     86     }
     87 }
     88 void check1(brid B,int i[],int o[],int temp)//检查入口内撞墙函数
     89 {
     90     int k,f,b[5],c[5],q[3];
     91     q[0]=77,q[1]=78,q[2]=76;
     92     b[0]=0;b[1]=16;b[2]=31;b[3]=46,b[4]=61;//b为左
     93     c[0]=2;c[1]=18,c[2]=33,c[3]=48,c[4]=63;    //C为右
     94     for(int f=0;f<3;f++){
     95     for(k=0;k<=4;k++)
     96     {
     97         if((B.x-f==q[f]-i[k]+b[k]&&B.y==o[k]+6-temp)||(B.x-f==q[f]-i[k]+c[k]&&B.y==o[k]+6-temp)){
     98         Position(B.x,B.y);Br;printf("
    ");Position(B.x,B.y+1);
     99         printf("Lost the game!
    ");system("pause");
    100      }
    101         if((B.x-f==q[f]-i[k]+b[k]&&B.y>=o[k]+temp-1)||(B.x-f==q[f]-i[k]+c[k]&&B.y>=o[k]+temp-1)){
    102         Position(B.x,B.y);Br;printf("
    ");Position(B.x,B.y+1);
    103         printf("Lost the game!
    ");system("pause");
    104      }        
    105     }//判断右侧
    106    }
    107 }
      
    1
    void fangkuai(brid B,int y) 2 //此函数中的烟囱可以用一条函数表达,再调用5次,但是难度会更大。 3 //此函数为全局调用函数,历史2小时完成。 4 //包括方块的建成和撞墙检查的调用 5 //一个方块在黑白框中占2个单位 6 { 7 int i[5],o[5],f[5],temp=6;//四变量分别是坐标、随机数、距离、难度控制(烟囱间隔) 8 srand((int)time(NULL));//int 随即种子 9 o[0]=rand()%8+4;o[1]=rand()%8+4;o[2]=rand()%8+4; 10 o[3]=rand()%8+4;o[4]=rand()%8+4;//先初始化5个随机数,用于首先引入方块的长度值 11 f[0]=0;f[1]=16;f[2]=31;f[3]=46,f[4]=61; 12 for(i[0]=0,i[1]=0,i[2]=0,i[3]=0,i[4]=0;i[0]<135, 13 i[1]<135,i[2]<137,i[3]<137,i[4]<139;//总循环,控制5烟囱的无限循环 14 i[0]++,i[1]++,i[2]++,i[3]++,i[4]++,B.y++){ 15 for(int k=2;k<=o[0];k++){ 16 Position(79-i[0],k);P;}//上左 17 for(int k=2;k<=26-o[0]-temp;k++){//25-26+o[0]+temp=temp-1+o[0] 18 Position(79-i[0],25-k);P;}//下左 19 if(i[0]==2||i[0]>2){ 20 for(int k=2;k<=o[0];k++){//上右 21 Position(79-i[0]+2,k);P;} 22 for(int k=2;k<=26-o[0]-temp;k++){ 23 Position(79-i[0]+2,25-k);P;//下右 24 } 25 } 26 if(i[0]==78){//达屏幕最左端,开始清屏,下同理。 27 for(int k=2;k<=o[0];k++) 28 { 29 Position(2,k);PR;//清理左边 30 Position(4,k);PR; 31 } 32 for(int k=2;k<=26-o[0]-temp;k++){//清理右边 33 Position(2,25-k);PR; 34 Position(4,25-k);PR; 35 } 36 if(i[4]>=76){//56+15=71,此处的if语句的作用是为了使两烟囱之间保持距离,距离为15/2像素 37 i[0]=0;//距离够了i【0】清0,从新从右边出烟囱 38 o[0]=rand()%8+4;//从新产生随机数 39 } 40 else i[0]=77;//否则,一直在左边等清屏 41 }//第一条烟囱完成 42 if(i[1]==16||i[1]>16){ 43 for(int k=2;k<=o[1];k++){ 44 Position(78-i[1]+16,k);P;} 45 for(int k=2;k<=26-o[1]-temp;k++){ 46 Position(78-i[1]+16,25-k);P; 47 } 48 } 49 if(i[1]==17||i[1]>17){ 50 for(int k=2;k<=o[1];k++){ 51 Position(78-i[1]+18,k);P;} 52 for(int k=2;k<=26-o[1]-temp;k++){ 53 Position(78-i[1]+18,25-k);P; 54 } 55 } 56 if(i[1]==92){ 57 for(int k=2;k<=o[1];k++) 58 { 59 Position(2,k);PR; 60 Position(4,k);PR; 61 } 62 for(int k=2;k<=26-o[1]-temp;k++){ 63 Position(2,25-k);PR; 64 Position(4,25-k);PR; 65 } 66 if(i[0]>=15){ 67 i[1]=14; 68 o[1]=rand()%8+4; 69 } 70 else i[1]=91; 71 }//第二条 72 if(i[2]==31||i[2]>31){ 73 for(int k=2;k<=o[2];k++){ 74 Position(78-i[2]+31,k);P;} 75 for(int k=2;k<=26-o[2]-temp;k++){ 76 Position(78-i[2]+31,25-k);P; 77 } 78 }// 79 if(i[2]==32||i[2]>32){ 80 for(int k=2;k<=o[2];k++){ 81 Position(78-i[2]+33,k);P;} 82 for(int k=2;k<=26-o[2]-temp;k++){ 83 Position(78-i[2]+33,25-k);P; 84 } 85 } 86 if(i[2]==108){ 87 for(int k=2;k<=o[2];k++) 88 { 89 Position(2,k);PR; 90 Position(4,k);PR; 91 } 92 for(int k=2;k<=26-o[2]-temp;k++){ 93 Position(2,25-k);PR; 94 Position(4,25-k);PR; 95 } 96 if(i[1]>=29){//14+15=29 97 o[2]=rand()%8+4; 98 i[2]=28; 99 } 100 else i[2]=107; 101 }//第三条 102 if(i[3]==46||i[3]>46){ 103 for(int k=2;k<=o[3];k++){ 104 Position(78-i[3]+46,k);P;} 105 for(int k=2;k<=26-o[3]-temp;k++){ 106 Position(78-i[3]+46,25-k);P; 107 } 108 } 109 if(i[3]==47||i[3]>47){ 110 for(int k=2;k<=o[3];k++){ 111 Position(78-i[3]+48,k);P;} 112 for(int k=2;k<=26-o[3]-temp;k++){ 113 Position(78-i[3]+48,25-k);P; 114 } 115 } 116 if(i[3]==122){ 117 for(int k=2;k<=o[3];k++) 118 { 119 Position(2,k);PR; 120 Position(4,k);PR; 121 } 122 for(int k=2;k<=26-o[3]-temp;k++){ 123 Position(2,25-k);PR; 124 Position(4,25-k);PR; 125 } 126 if(i[2]>=43){//28+15=43 127 o[3]=rand()%8+4; 128 i[3]=42; 129 } 130 else i[3]=121; 131 }//第四条 132 if(i[4]==61||i[4]>61){ 133 for(int k=2;k<=o[4];k++){ 134 Position(78-i[4]+61,k);P;} 135 for(int k=2;k<=26-o[4]-temp;k++){ 136 Position(78-i[4]+61,25-k);P; 137 } 138 } 139 if(i[4]==62||i[4]>62){ 140 for(int k=2;k<=o[4];k++){ 141 Position(78-i[4]+63,k);P;} 142 for(int k=2;k<=26-o[4]-temp;k++){ 143 Position(78-i[4]+63,25-k);P; 144 } 145 } 146 if(i[4]==138){ 147 for(int k=2;k<=o[4];k++) 148 { 149 Position(2,k);PR; 150 Position(4,k);PR; 151 } 152 for(int k=2;k<=26-o[4]-temp;k++){ 153 Position(2,25-k);PR; 154 Position(4,25-k);PR; 155 } 156 if(i[3]>=0){ 157 o[4]=rand()%8+4; 158 i[4]=56; 159 } 160 else i[4]=137; 161 }//第五条 162 feixing(B,y); 163 check1(B,i,o,temp); 164 if(GetAsyncKeyState(VK_UP)&&y>0) 165 B.y=B.y-2; 166 //if(GetAsyncKeyState(VK_DOWN)&&y>0) 167 //B.y=B.y+1; 168 //else if(B.y<=0) 169 check(B,i,o,temp); 170 for(int k=0;k<=4;k++){ 171 if(B.x==79-i[k]+f[k]) 172 {B.score++;}//记录鸟超过的烟囱数并累加分数 173 } 174 fenshuYUnandu(B,i,o); 175 if(B.score%20==0&&B.x==78-i[4]+63)//烟囱入口变小 176 temp--; 177 } 178 }

    最后的main函数

     1 int main()
     2 {
     3     brid B;
     4     B.x=23;B.y=10;B.score=0;//初始鸟的位置和初始分数
     5     int x=23,y=10;//初始分界线的位置
     6     jiemian1();
     7     system("cls"); 
     8     jiemian();
     9     fangkuai(B,y);    
    10     return 0;
    11 }

    效果图片:

      

  • 相关阅读:
    Windows2003服务器IIS启用Gzip压缩
    使用CDN加速后网站不能使用HttpWebRequest提交数据
    隐藏其它数据库,只让用户能够看到自己拥有权限的数据库
    磁盘阵列的基本概念
    前端构建相关
    一个日志记录类
    手把手教你做个splash(屏幕启动)
    调试问题及解决方案集锦
    c#
    。net中各大编程网址
  • 原文地址:https://www.cnblogs.com/linguanh/p/4086968.html
Copyright © 2020-2023  润新知