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("____________________________________________________________________________\n");
 20     printf(" ■\n");
 21     printf(" ■\n");
 22     printf(" ■C语言非链表版:Flappy Bird\n");
 23     printf(" ■编写人:LinGuanH\n");
 24     printf(" ■日期:2014.7.30\n");
 25     printf(" ■耗时:4小时37分\n");
 26     printf(" ■游戏说明:\n");
 27     printf(" ■1-按键盘中的上箭头使鸟起飞\n");
 28     printf(" ■2-分数每过20,难度增大,烟囱入口减小!\n");
 29     printf(" ■3-光标显示方式为中文鸟字\n");
 30     printf(" ■4-介于VS中graphics.h函数库使用失败,导致原图插入不了,所用转用黑白框。\n");
 31     printf(" ■5-撞墙失败,游戏会提示输了,但是不会return 0,你可以继续按方向键接着玩。\n");
 32     printf(" ■\n");
 33     printf(" ■\n");
 34     printf(" ■\n");
 35     printf(" ■代码内带有注释,感兴趣的可以直接修改,增加其他效果\n");
 36     printf(" ■必然存在bug,找到了麻烦跟我说声,谢谢。\n");
 37     printf(" ■请按键盘的任意一个键继续。\n");
 38     printf(" ■\n");
 39     printf(" ■\n");
 40     printf(" ■\n");
 41     printf(" ____________________________________________________________________________\n");
 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("\n");Position(B.x,B.y+1);
 80                 printf("Lost the game!\n");system("pause");
 81           }
 82        }    
 83     if(B.y>=24||B.y<=1.5){
 84                 printf("Lost the game!\n");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("\n");Position(B.x,B.y+1);
 99         printf("Lost the game!\n");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("\n");Position(B.x,B.y+1);
103         printf("Lost the game!\n");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 }

效果图片:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏菜鸟前端工程师

JavaScript学习笔记019-原生js运动框架0时间运动框架

772
来自专栏偏前端工程师的驿站

CSS魔法堂:深入理解line-height和vertical-align

前言 一直听说line-height是指两行文本的基线间的距离,然后又说行高等于行距,最近还听说有个叫行间距的家伙,@张鑫旭还说line-height和vert...

2298
来自专栏码匠的流水账

聊聊Color中的alpha值

color对象里头的alpha其实是指不透明度,其值范围为0-255,越大越不透明。 其通常对应opacity,这个就是单词语义表达的不透明度,其值范围[0,1...

672
来自专栏difcareer的技术笔记

OpenGL API 简介

开发基于 OpenGL 的应用程序,必须先了解 OpenGL 的库函数。它采用 C 语言风格,提供大量的函数来进行图形的处理和显示。OpenGL 库函数的命名方...

744
来自专栏一“技”之长

iOS开发CoreGraphics核心图形框架之五——Patterns模型的应用

    Patterns称为模型可能并不直观,说一个场景我们或许就可以更加容易的理解Patterns。在开发中,开发者经常会遇到这样的需求,将某个图片或者某个图...

833
来自专栏听雨堂

MapX中取得图元操作的速度测试

        最常见的操作,是取得图层中的某个图元。假如需要根据一个属性(无重复)来获得图元的话,发现速度相差极大。 遍历比较是最慢的。 用图层的search...

1886
来自专栏Golang语言社区

Go项目开发----2048小游戏(上)

刚接触go语言不久,前段时间看到一个2048的项目开发教程,于是就试着练了下手。我的环境采用的是Ubuntu Linux环境。 源码下载: https://gi...

2634
来自专栏菩提树下的杨过

Flash/Flex学习笔记(56):矩阵变换

先回顾一下Silvelright中的矩阵变换[转]WPF中的MatrixTransform,简单点讲:矩阵变换能改变对象的x,y坐标,x或y方向上的缩放,以及对...

18510
来自专栏自动化测试实战

HTML第五课——css盒子模型【2】

733
来自专栏逍遥剑客的游戏开发

Nebula3中的模型

1147

扫码关注云+社区