c语言入门级小游戏飞机2.0版-激发你的编程兴趣100150行代码
c语言入门级小游戏·飞机(2.0版)| 激发你的编程兴趣(100~150行代码)
目录
前言
声明:本游戏参考《c语言课程设计与游戏开发实践教程》。
首先放一个小游戏视频效果(右边界有点凌乱,影响美观,但不影响效果,多多见谅😋)
game飞机2.0版
如何?这个单单用字符来完成的简略版小游戏,很适合c语言的新手锻炼实践能力(理论即可)。这个2.0版的飞机小游戏实际上是在我上次发的1.0版基础上优化的( )相比之下,2.0版不再有画面和光标的频闪问题,发射方式从激光变成子弹,障碍物可移动并重现,有计分功能。
- 本游戏必备知识点:printf输出,for语句,if语句,while循环,函数的自定义和引用,自增自减运算符。
- 本游戏 会介绍 的知识点:标识符的命名,两种清屏函数,rand函数,方便的getch函数,kbhit函数,隐藏光标函数。(如果不知道这些小知识点并 不影响 ,看了介绍和应用很基本就可以理解)。
制作可以自由移动并且发射子弹的飞机
介绍第一种清屏函数system(“cls”)
- 该函数位于stdlib.h函数库,头文件要机上#include <stdlib.h>。
- 作用:该函数可以在循环中清空上一次的画面,在这里实现飞机的自由移动(要不然飞机移动就跟重影一样,跟李白技能一样)
- 使用:system(“cls”);
介绍kbhit函数
- 这个函数在conio.h函数库中,头文件要加上#include <conio.h>。
- 我们在这里是这样使用:if(kbhi()) {输入…运行…}
- 作用:该函数可以判断是否有输入,并且防止程序运行堵塞。一般情况下,如果有输入函数出现,程序会停下来等待输入,这时候程序就堵塞住了。kbhit的作用就是不让程序这时候发生堵塞。如果有输入,那么if内相应程序会运行;如果没有输入,if外程序仍然可以运行。
介绍方便的getch()函数
- 该函数位于conio.h函数库中,头文件要加上#include <conio.h>。
- 作用:getch()函数只接受单字符。原本的scanf会在输入之后按下回车键才能继续运行,但是getch()函数接受单个字符之后不需要按回车键就会结束输入,继续运行。
- 使用:a=grtch();
直接上代码,代🐎中有详细的注释解析哦
#include <stdio.h>
#include <stdlib.h> //system函数库
#include <conio.h> //getch函数库 ,kbhit函数库
//飞机可移动,有子弹
//定义几个全局变量,方便所有函数使用
int x,y; //飞机坐标
int high,width; //画面宽度
int billx,billy; //子弹坐标
void start() //第一个自定义函数,作用是使数据初始化
{ //一个不冷不热的知识:全局变量不能在函数外赋值,能在任意函数中赋值
high=20;
width=30;
x=width/2;
y=high/2;
billx=x;
billy=0;
}
void show() //第二个函数,显示飞机和边界
{
int i,n;
system("cls");//这个清屏函数其实放很多地方都行 ,只要是在死循环里
for(i=0;i<high;i++) //外层循环,用于输出回车和左右边界
{
printf("#"); //用于输出左侧边界
for(n=0;n<width;n++) //内层循环,用于输出空格、飞机、上下边界
{if((i==y)&&(n==x))
printf(" +");//&&两侧运算式最好都加()
else {
if((i==0)||(i==19))
printf("#"); //划定上下边界
else
if((i==billy)&&(n==billx))
printf(" |"); //输出子弹。前面加三个空格,因为要和飞机头照齐
else
if((i==y+1)&&(n==x))
printf("+---+");
else
if((i==y+2)&&(n==x))
printf(" * *");
else
printf(" ");//没错就是套娃,这个过程是在输出整个飞机体
}
}
printf("#"); //输出右方边界
//如果飞机移动时超出界限就会消失。但飞机仅仅是看不见了,实际上还存在
printf("\n");
}
}
void unput() //第三个自定义函数,用于控制子弹
{
if(billy>-1)
billy--; //目的是让子弹一直往上飞
}
void put() //第四个函数,输入字符控制飞机移动、放出子弹
{
char move;
if(kbhit())
{
move=getch();
if(move=='a')x--;
if(move=='d')x++;
if(move=='w')y--;
if(move=='s')y++;
if(move==' '){
billx=x-1;
//因为边界占一个字节位置,如果不-1会让子弹和飞机错开一个位置
billy=y-1; //因为要让子弹在飞机上一行输出
}
}
}
int main()
{
start(); //第一个函数
while(1) //1代表正确,0代表非,所以while(1)一直满足条件,无限循环
{
// system("cls");清屏函数加这也行
show(); //第二个函数
unput(); //第三个函数
put(); //第四个函数
//再次引用函数的时候不需要加数据类型
}
return 0;
}
添加可以自己移动、击落后会重生的障碍物
标识符的命名
标识符一般包括变量名、常量名、函数名…
- 标识符中可以有大小写字母、数字、下划线-、$。不可以有汉字和其他符号。
- 标识符不能以数字开头。
- 标识符中区分大小写。
介绍rand函数
- 属于stdlib.h函数库,头文件要加上#include<stdlib.h>。
- 作用:使一个东西在一定范围内随机出现。在这里就是让障碍物小时候再重现
- 使用方式:a=rand()%rage;
(a是一个随机变量,在这里表示障碍物横坐标;rage是横坐标可以出现的宽度范围。在代码的运用中可以帮助你更好地理解作用)
来,上代码!(代码中每一步有详解)
#include <stdio.h>
#include <stdlib.h>//system函数库
#include <conio.h>//getch函数库
#include <windows.h>//void gotoxy(int x,int y)和HideCursor()函数库
int x,y; //飞机的位置
int high,width; //画面宽度
int billx,billy; //子弹
int enermy_x,enermy_y;//敌机 。
int score;
//定义全局变量
void start() //第一个自定义函数,作用是使数据初始化
{ //一个不冷不热的知识:全局变量不能再函数外赋值,能在任意函数中赋值
high=20;
width=30;
x=width/2;
y=high/2;
billx=x;
billy=0;
enermy_x=x+5;
enermy_y=2;
score=0;
}
void show()//第二个函数,显示飞机
{
int i,n;
system("cls");//这个清屏函数其实加很多地方都行 ,只要是在死循环里
for(i=0; i<(high); i++)
{
printf("#");
for(n=0; n<width; n++)
{ if((i==y)&&(n==x))
printf(" +");//&&两侧运算式最好都加()。为了和身体对称,前面加空格
else {
if((i==0)||(i==19))
printf("#"); //划定上下界限
else
if((i==billy)&&(n==billx))
printf(" |");
else
if((i==enermy_y)&&(n==enermy_x))
printf("*"); //输出障碍物,障碍物长啥样都可以
else
if((i==y+1)&&(n==x))
printf("+---+");
else
if((i==y+2)&&(n==x))
printf(" * *");
else
printf(" ");
//没错这就是套娃
}
}
printf("#");
//划定左右界限,如果飞机移动时超出界限会消失,飞机仅仅是看不见,实际上还存在。
printf("\n");
}
}
void unput() //第三个函数,控制子弹飞行、控制障碍物掉落和消失重现
{
if(billy>-1)
billy--;//目的是让子弹一直往上飞
if((billx==enermy_x)&&(billy==enermy_y))
{
score++;
enermy_y=0;//让障碍物从顶上掉下来
enermy_x=rand()%width;//意思就是在该宽度范围内随机出现
billx=-2;
//子弹横坐标为负,子弹就不再出现在画面内。产生了使子弹被击中后消失的效果
}
static int speed=0; //static使得该变量作用域仅仅在当前函数内
if(speed==20){
enermy_y++;
speed=0;
}
else speed++;
//让敌机每循环20次下落一次,要不然掉的太快打不中
//这里两种表示方法都生效
}
void put() //第四个函数,通过输入端控制飞机移动并发射子弹
{
char move;
if(kbhit())
{
move=getch();
if(move=='a')x--;
if(move=='d')x++;
if(move=='w')y--;
if(move=='s')y++;
if(move==' ') {
billx=x;
billy=y-1;//因为要让子弹在飞机上方输出
}
}
}
int main()
{
start();
while(1)
{
// system("cls");加这也行
show();
unput();//再次引用函数的时候不要加数据类型
put();
}
return 0;
}
加上计分板,优化频闪问题
该游戏已经基本制作完成。这时候你会发现画面闪烁很厉害,而且光标的频闪也很影响美观。因此,这一步我们加上两个函数,分别优化画面频闪和光标频闪问题。同时加上计分板,统计击中障碍物个数。
介绍gotoxy函数
这个函数代替了上一个清屏函数system函数,解决画面频闪问题。不用管任何别的东西,直接输入下面的函数内容。
void gotoxy(int x,int y)
{
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X=x;
pos.Y=y;
SetConsoleCursorPosition(handle,pos);
}
介绍HideCursor函数
该函数作用是隐藏光标,解决光标频闪问题。使用方法如下(直接用)
void HideCursor()
{
CONSOLE_CURSOR_INFO cursor_info={1,0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
}
加上这最后两个函数,游戏画面就会变得更加清晰稳定啦!最后给大家放上完整代码👇🏻
完整代码
#include <stdio.h>
#include <stdlib.h>//system函数库
#include <conio.h>//getch函数库
#include <windows.h>//void gotoxy(int x,int y)和HideCursor()函数库
//发挥
int x,y;//飞机的位置
int high,width;//画面宽度
int billx,billy; //子弹
int enermy_x,enermy_y;//敌机 。知识点标识符的用法
int score;
//定义全局变量
void gotoxy(int x,int y) //清屏
{
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X=x;
pos.Y=y;
SetConsoleCursorPosition(handle,pos);
}
void start() //第一个自定义函数,作用是使数据初始化
{ //一个不冷不热的知识:全局变量不能再函数外赋值,能在任意函数中赋值
high=20;
width=30;
x=width/2;
y=high/2;
billx=x;
billy=0;
enermy_x=x+5;
enermy_y=2;
score=0;
}
void show()//第二个函数,显示飞机
{
int i,n;
gotoxy(0,0); //将清屏函数引用进来
//system("cls");//这个清屏函数其实加很多地方都行 ,只要是在死循环里
for(i=0; i<(high); i++)
{
printf("#");
for(n=0; n<width; n++)
{ if((i==y)&&(n==x))
printf(" +");
else {
if((i==0)||(i==19))
printf("#");//划定上下界限
else
if((i==billy)&&(n==billx))
printf("|");
else
if((i==enermy_y)&&(n==enermy_x))
printf("*");
else
if((i==y+1)&&(n==x))
printf("+---+");
else
if((i==y+2)&&(n==x))
printf(" * *");
else
printf(" ");//没错就是套娃
}
}
printf("#");//划定左右界限,如果飞机移动时超出界限就会消失,划定界限会提醒你自己,不然飞机怎么没了都不知道 。飞机仅仅是不见了,但是还存在
printf("\n");
}
printf("Your's score is%d",score); //在画面最后部分输出计分板
}
void unput()//第三个函数
{
static int speed=0;//作用域仅仅在当前函数
int replace=20;//确实有调节素的的作用,不过超过一定数字之后就不会再次显示了
if(billy>-1)
billy--;//目的是让子弹一直往上飞
if((billx==enermy_x)&&(billy==enermy_y))
{
score++;
enermy_y=0;//让障碍物从顶上掉下来
enermy_x=rand()%(width);//意思就是在宽度范围内的最上方可以随机出现
billx=-2;//让子弹击中障碍物之后消失
replace--;
}
// if(speed!=10)speed++;
if(speed==replace){
enermy_y++;
speed=0;
}
else speed++;
//让敌机每循环十次下落一次
//这里两种表示方法都生效
}
void put()//第四个函数,控制移动
{
char move;
if(kbhit())
{
move=getch();
if(move=='a')x--;
if(move=='d')x++;
if(move=='w')y--;
if(move=='s')y++;
if(move==' ') {
billx=x+2;
billy=y-1;//因为要让子弹在飞机上方输出
}
}
}
void HideCursor() //隐藏光标函数
{
CONSOLE_CURSOR_INFO cursor_info={1,0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
}
int main()
{
start();
while(1)
{
show();
unput();//再次引用函数的时候不要加数据类型
put();
HideCursor(); //引用隐藏光标函数
}
return 0;
}
最后有2个小思考题:1.如何使用esc键暂停游戏? 2.如何使分数越高障碍物下落速度越快?
这两个问题目前我也没有解决,如果你们解决了请务必教教我🙏🏻
如果用不懂得地方可以随时评论或者私信我哦
就酱,拜拜~