上一节,其实我们的弹球游戏基本就已经完成了,但有些不够好,比如程序一开始,小球从中间开始运动,速度过快反应慢的话马上就game over了,因此我们可以加一个开始的提示,比如确认开始;以及在结束时提示是否继续开始或结束,来提高游戏的友好度。
对于第一部分,我们直接用outtextxy在游戏界面中间输出就可以,然后写个循环接受,代码如下:
outtextxy(WIDTH-500, HIGH-350, "欢迎体验,请按C键开始..."); while(1) { Sleep(50); if(GetAsyncKeyState(67) & 0x8000 ) { break; } }
对于游戏结束后,我们可以给与用户提示,让用户自行选择是继续玩还是退出,可以在游戏结束的时候询问用户,如笔者这里让用户选择按C是继续玩,按Q是退出。效果如下:
判定小球触碰到底部游戏结束后,则给与用户提示,若选择重新开始,则清空成绩、清空提示,重新开始即可,效果如下:
核心实现并不难,主要在于逻辑分支,笔者这里使用了goto完成,完整参考代码如下:
//弹球游戏 //www.dotcpp.com #include <graphics.h> // 引用图形库头文件 #include <conio.h> #include <stdio.h> #define WIDTH 640 #define HIGH 480 #define R 10 #define STEP 10 int Board_x1=150,Board_y1=HIGH-5,Board_x2=250,Board_y2=HIGH; int pause() //暂停 { while(1) { Sleep(100); if(GetAsyncKeyState(67) & 0x8000 ) { break; } } return 0; } int main() { int i; char ch; int score=0; char ScoreBuffer[100]={"当前分数: 0"}; int Vx=3,Vy=3; int x=(WIDTH-200)-200,y=HIGH/2; //表示小球初始圆心坐标 initgraph(WIDTH, HIGH); // 创建绘图窗口 640x480 像素 fillrectangle(WIDTH-200,0,WIDTH-195,HIGH);//绘制右墙 outtextxy(WIDTH-150, HIGH-350, ScoreBuffer); outtextxy(WIDTH-160, HIGH-250, ("按P暂停 按C继续")); outtextxy(WIDTH-160, HIGH-270, ("按A向左 按D向右")); Start: //初始化分数、小球位置信息 x=(WIDTH-200)-200,y=HIGH/2; score=0; outtextxy(WIDTH-500, HIGH-350, "欢迎体验,请按C键开始..."); while(1) { Sleep(50); if(GetAsyncKeyState(67) & 0x8000 ) { break; } } //用背景色清空提示语 setcolor(BLACK); outtextxy(WIDTH-500, HIGH-350, "欢迎光临,请按C键开始..."); BeginBatchDraw(); while(1) { x=x+Vx; y=y+Vy; //绘制小球 setfillcolor(GREEN); fillcircle(x,y,R); //绘制挡板 setfillcolor(YELLOW); fillrectangle(Board_x1,Board_y1,Board_x2,Board_y2); //显示分数 settextcolor(WHITE); sprintf(ScoreBuffer,"%s%d","当前分数: ",score); outtextxy(WIDTH-150, HIGH-350, ScoreBuffer); FlushBatchDraw(); Sleep(5); //原位置擦除小球图案 setcolor(BLACK); setfillcolor(BLACK); fillcircle(x,y,R); //原位置擦除挡板 setfillcolor(BLACK); fillrectangle(Board_x1,Board_y1,Board_x2,Board_y2); if(GetAsyncKeyState(65) & 0x8000) //向左 { if(Board_x1-STEP<=0) { Board_x1=0; Board_x2=100; } else { Board_x1=Board_x1-STEP; Board_x2=Board_x2-STEP; } } if(GetAsyncKeyState(68) & 0x8000) //向右 { if(Board_x2+STEP>=WIDTH-205) { Board_x1=WIDTH-305; Board_x2=WIDTH-205; } else { Board_x1=Board_x1+STEP; Board_x2=Board_x2+STEP; } } if(GetAsyncKeyState(80) & 0x8000)//暂停 { pause(); } if(x<=R || x>=WIDTH-203-R) { Vx=-Vx; } if(y<=R) { Vy=-Vy; } //触底 if(y>=HIGH-R-5) { if(x>=Board_x1-R && x<=Board_x2+R) //是否在板子上 { Vy=-Vy; //重新计算并显示分数 //clearrectangle(WIDTH-150, HIGH-350,WIDTH-50,HIGH-400); settextcolor(BLACK); outtextxy(WIDTH-150, HIGH-350, ScoreBuffer); score=score+10; sprintf(ScoreBuffer,"%s%d","当前分数: ",score); settextcolor(WHITE); outtextxy(WIDTH-150, HIGH-350, ScoreBuffer); } else//游戏结束 { settextcolor(WHITE); //setbkmode(TRANSPARENT); outtextxy(WIDTH-500, HIGH-350, ("游戏结束!Game Over!")); outtextxy(WIDTH-500, HIGH-330, ("按C继续,按Q退出")); fflush(stdin); FlushBatchDraw(); while(1) { Sleep(50); if(GetAsyncKeyState(67) & 0x8000 ) //C { //清空提示信息,重新开始 setcolor(BLACK); outtextxy(WIDTH-500, HIGH-350, ("游戏结束!Game Over!")); outtextxy(WIDTH-500, HIGH-330, ("按C继续,按Q退出")); settextcolor(BLACK); outtextxy(WIDTH-150, HIGH-350, ScoreBuffer); goto Start; } if(GetAsyncKeyState(81) & 0x8000 )//Q { exit(0); } } } } } EndBatchDraw(); getch(); // 按任意键继续 closegraph(); // 关闭绘图窗口 return 0; }
每一版对于前面版本而言除了正文讲述的功能之外,都有一些小修改,如为了后面的升级做的修改,都是基于当下的思考而来的。总体而言,基本功能已经实现,大家可以继续完善,如增加难度选择、晋级功能、成绩保存等等。
欢迎交流~
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程