C语言——函数的综合运用。自定义函数,gotoxy清屏函数与HideCursor隐藏光标,防闪屏,共同制作打飞机游戏。

简介: ①在变量中,我们必须进行定义赋值初始化后,才能在程序中使用,所以需要一个“地方”,整理好这些变量,在程序中整洁一些void startup() //数据初始化②打出画面中所显示的所需代码,也给一个函数void show() //显示画面③在游戏运行中,飞机的移动,发射等操作必须使用键盘,此时就要进行输入判断,给出相应的函数,实行不同的命令 ,其中分为两种,一种是程序运行时对输入做出变化,另一种是不变化void updateWithoutInput() //与用户输入无关的更新。

目录

制作准备

1.所需头函数

2.自定义函数

3.设置全局变量

4.清屏函数

5.画面布置

6.成果


制作准备

1.所需头函数

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<windows.h>

image.gif

2.自定义函数

①在变量中,我们必须进行定义赋值初始化后,才能在程序中使用,所以需要一个“地方”,整理好这些变量,在程序中整洁一些

void startup()          //数据初始化

image.gif

②打出画面中所显示的所需代码,也给一个函数

void show()            //显示画面

image.gif

③在游戏运行中,飞机的移动,发射等操作必须使用键盘,此时就要进行输入判断,给出相应的函数,实行不同的命令 ,其中分为两种,一种是程序运行时对输入做出变化,另一种是不变化

void updateWithoutInput()       //与用户输入无关的更新
void updateWithInput()          //与用户有关的更新

image.gif

最后,必不可少的主函数,把它们全部包起来

int main()
{
    startup();
    while(1)
    {
        show();
        updateWithoutInput();
        updateWithInput();
        HideCursor();      
    }
    return 0;
}

image.gif

3.设置全局变量

首先我们先理解控制台的xy轴方位,这与我们平时所学的数学正方向坐标轴不同,命令提示符窗口

竖方向为X轴,横方向为Y轴。

其中向下为X轴正方向,向右为Y轴正方向

image.gif编辑

知道这一点后我们便开始考虑所需要的变量

    1. 窗口大小(高度宽度)
    2. 飞机位置
    3. 子弹位置
    4. 敌机位置
    5. 分数统计

    大概有以上几种基本内容,所以我们进行定义

    int position_x,position_y;   //飞机位置
    int high,width;           //游戏画面尺寸
    int bullet_x,bullet_y;    //子弹位置
    int enemy_x,enemy_y;      //敌机位置
    int score;                //分数

    image.gif

    定义后,便在startup()函数中进行初始化

    void startup()          //数据初始化
    {
        high = 20;
        width = 30;
        position_x = high/2;       //飞机
        position_y = width/2;      
        bullet_x = -2;             //子弹
        bullet_y = position_y;
        enemy_x = 0;               //敌机
        enemy_y = position_y;
        score = 0;                 //分数
    }

    image.gif

    4.清屏函数

    第一种是使用清屏函数system("cls");实现屏幕的刷新

    (需要配上#include<stdlib.h>使用)

    优点:无需太多代码,简单易懂

    缺点:屏幕闪烁严重,影响视觉

    第二种使用gotoxy()函数。

    void gotoxy(int x,int y)    //将光标移动到(x,y)位置
    {
        HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);    //获取标准输出设备句柄
        COORD pos={x,y};      //坐标位置
        SetConsoleCursorPosition(handle,pos);   //设置控制台光标位置
    }
    void HideCursor()
    {
        CONSOLE_CURSOR_INFO cursor_info={1,0};  //0表示隐藏光标
        SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
    }

    image.gif

    优点:屏幕无闪动,轨迹清晰

    缺点:仍有光标不停移动(由于过于高级,所以不需要特意背诵,需要时调用出来就好)

    此时可上面的HideCursor()进行光标的隐藏


    5.画面布置

    一个游戏,总得有点画面出现吧,总不能是一块黑布,啥也没有,所以呢,我们得把飞机,敌机,计数得分,子弹等等都printf()出来

    这里呢,则是使用的for和else-if的嵌套使用⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇放到了我们之前预备好的自定义show函数里

    void show()            //显示画面
    {
        gotoxy(0,0);       //光标移动到原点位置,以下重画清屏
        int i,j;
        for(i=0;i<high;i++)
        {
            for(j=0;j<width;j++)
            {
                if((i==position_x)&&(j==position_y))
                    printf("*");    //输出飞机*
                else if((i==enemy_x)&&(j==enemy_y))
                    printf("@");    //输出敌机
                else if((i==bullet_x)&&(j==bullet_y))
                    printf("||");    //输出子弹
                else
                    printf(" ");    //输出空格
            }
            printf("\n");
        }
        printf("得分:%d\n",score);
    }

    image.gif

    在上文说到,有两种状态,一种在输入时(即敲打键盘移动、发射)要随之更新,另一种则后台自动更新(敌机的自动移动,分数的自动统计)

    很重要的一点,控制飞机的速度,我们使用了if循环,十次循环更新一次敌机位置

    (其实还是快了点)

    void updateWithoutInput()       //与用户输入无关的更新
    {
        if(bullet_x>-1)
        bullet_x--;
        // 用来控制敌机移动速度
        // 这样修改,虽然用户按键的交互速度还是很快,
        // 但NPC移动速度降低
        static int speed = 0;
        if(speed<10)
        {
            speed++;
        }
        if(speed==10)
        {
            enemy_x++;
            speed = 0;
        }
    //击中飞机时:加分
        if((bullet_x==enemy_x)&&(bullet_y==enemy_y))
        {
            score++;                  //分数加1
            enemy_x = -1;             //产生新的飞机
            enemy_y = rand()%width;
            bullet_x = -2;            //子弹无效
        }
    //未击中飞机时;飞机离开
        if(enemy_x>high)              //敌机跑出显示屏幕
        {
            enemy_x = -1;             //产生新的飞机
            enemy_y = rand()%width;
        }
    }

    image.gif

    这时就要注意末尾的一个代码,需要特别重视,在我的另一篇博客的末尾有提及(一丢丢)

    C语言程序入门——if-else及switch分支结构与for、do-while循环1.1.2

    不废话,就是这个rand()%width,让系统自动调用一个随机数,从而在循环中达到随机位置输出敌机的作用


    这是与用户输入无关的更新,那接下来就是与用户输入有关的更新了

    即游戏四键 “上上下下左右左右(BABA)”(doge保命)还有一个发射子弹(此处使用空格)

    正常代码中进行下一步时,需使用回车确认,很明显,我们打游戏总不能走一步用一次回车嘛,由此我们引申出——kbhit()


    kbhit是一个无阻碍函数,可以在输入时直接进入后续代码而不卡位置,实现输入即反馈

    而与之相反,我们使用阻碍函数getch()实现输入WSAD后进行相应的上下左右移动

    6.成果

    到了最后,串起来的完整代码附在文末

    #include<stdio.h>
    #include<stdlib.h>
    #include<conio.h>
    #include<windows.h>
    void gotoxy(int x,int y)    //将光标移动到(x,y)位置
    {
        HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);    //获取标准输出设备句柄
        COORD pos={x,y};      //坐标位置
        SetConsoleCursorPosition(handle,pos);   //设置控制台光标位置
    }
    void HideCursor()
    {
        CONSOLE_CURSOR_INFO cursor_info={1,0};  //0表示隐藏光标
        SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
    }
    //全局变量
    int position_x,position_y;   //飞机位置
    int high,width;           //游戏画面尺寸
    int bullet_x,bullet_y;    //子弹位置
    int enemy_x,enemy_y;      //敌机位置
    int score;
    void startup()          //数据初始化
    {
        high = 20;
        width = 30;
        position_x = high/2;       //飞机
        position_y = width/2;      
        bullet_x = -2;             //子弹
        bullet_y = position_y;
        enemy_x = 0;               //敌机
        enemy_y = position_y;
        score = 0;                 //分数
    }
    void show()            //显示画面
    {
        gotoxy(0,0);       //光标移动到原点位置,以下重画清屏
        int i,j;
        for(i=0;i<high;i++)
        {
            for(j=0;j<width;j++)
            {
                if((i==position_x)&&(j==position_y))
                    printf("*");    //输出飞机*
                else if((i==enemy_x)&&(j==enemy_y))
                    printf("@");    //输出敌机
                else if((i==bullet_x)&&(j==bullet_y))
                    printf("||");    //输出子弹
                else
                    printf(" ");    //输出空格
            }
            printf("\n");
        }
        printf("得分:%d\n",score);
    }
    void updateWithoutInput()       //与用户输入无关的更新
    {
        if(bullet_x>-1)
        bullet_x--;
        // 用来控制敌机移动速度
        // 这样修改,虽然用户按键的交互速度还是很快,
        // 但NPC移动速度降低
        static int speed = 0;
        if(speed<10)
        {
            speed++;
        }
        if(speed==10)
        {
            enemy_x++;
            speed = 0;
        }
    //击中飞机时:加分
        if((bullet_x==enemy_x)&&(bullet_y==enemy_y))
        {
            score++;                  //分数加1
            enemy_x = -1;             //产生新的飞机
            enemy_y = rand()%width;
            bullet_x = -2;            //子弹无效
        }
    //未击中飞机时;飞机离开
        if(enemy_x>high)              //敌机跑出显示屏幕
        {
            enemy_x = -1;             //产生新的飞机
            enemy_y = rand()%width;
        }
    }
    void updateWithInput()          //与用户有关的更新
    {
        char input;
        if(kbhit())      //根据用户的不同输入来移动,不必输入回车
        {
            input = getch();
            if(input=='a')
                position_y--;
            if(input=='d')
                position_y++;
            if(input=='w')
                position_x--;
            if(input=='s')
                position_x++;
            if(input==' ')
            {
                bullet_x = position_x-1;    //从飞机正上方发生子弹
                bullet_y = position_y;
            }
        }
    }
    int main()
    {
        startup();
        while(1)
        {
            show();
            updateWithoutInput();
            updateWithInput();
            HideCursor();       //隐藏光标
        }
        return 0;
    }

    image.gif

    学艺不精,多多包涵

    相关文章
    |
    1月前
    |
    存储 算法 C语言
    【C语言程序设计——函数】素数判定(头歌实践教学平台习题)【合集】
    本内容介绍了编写一个判断素数的子函数的任务,涵盖循环控制与跳转语句、算术运算符(%)、以及素数的概念。任务要求在主函数中输入整数并输出是否为素数的信息。相关知识包括 `for` 和 `while` 循环、`break` 和 `continue` 语句、取余运算符 `%` 的使用及素数定义、分布规律和应用场景。编程要求根据提示补充代码,测试说明提供了输入输出示例,最后给出通关代码和测试结果。 任务核心:编写判断素数的子函数并在主函数中调用,涉及循环结构和条件判断。
    63 23
    |
    1月前
    |
    算法 C语言
    【C语言程序设计——函数】利用函数求解最大公约数和最小公倍数(头歌实践教学平台习题)【合集】
    本文档介绍了如何编写两个子函数,分别求任意两个整数的最大公约数和最小公倍数。内容涵盖循环控制与跳转语句的使用、最大公约数的求法(包括辗转相除法和更相减损术),以及基于最大公约数求最小公倍数的方法。通过示例代码和测试说明,帮助读者理解和实现相关算法。最终提供了完整的通关代码及测试结果,确保编程任务的成功完成。
    68 15
    |
    1月前
    |
    C语言
    【C语言程序设计——函数】亲密数判定(头歌实践教学平台习题)【合集】
    本文介绍了通过编程实现打印3000以内的全部亲密数的任务。主要内容包括: 1. **任务描述**:实现函数打印3000以内的全部亲密数。 2. **相关知识**: - 循环控制和跳转语句(for、while循环,break、continue语句)的使用。 - 亲密数的概念及历史背景。 - 判断亲密数的方法:计算数A的因子和存于B,再计算B的因子和存于sum,最后比较sum与A是否相等。 3. **编程要求**:根据提示在指定区域内补充代码。 4. **测试说明**:平台对代码进行测试,预期输出如220和284是一组亲密数。 5. **通关代码**:提供了完整的C语言代码实现
    61 24
    |
    1月前
    |
    存储 C语言
    【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
    本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
    66 16
    |
    1月前
    |
    存储 编译器 C语言
    【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
    函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
    37 3
    |
    1月前
    |
    存储 算法 安全
    【C语言程序设计——函数】分数数列求和1(头歌实践教学平台习题)【合集】
    if 语句是最基础的形式,当条件为真时执行其内部的语句块;switch 语句则适用于针对一个表达式的多个固定值进行判断,根据表达式的值与各个 case 后的常量值匹配情况,执行相应 case 分支下的语句,直到遇到 break 语句跳出 switch 结构,若没有匹配值则执行 default 分支(可选)。例如,在判断一个数是否大于 10 的场景中,条件表达式为 “num> 10”,这里的 “num” 是程序中的变量,通过比较其值与 10 的大小关系来确定条件的真假。常量的值必须是唯一的,且在同一个。
    20 2
    |
    1月前
    |
    存储 编译器 C语言
    【C语言程序设计——函数】回文数判定(头歌实践教学平台习题)【合集】
    算术运算于 C 语言仿若精密 “齿轮组”,驱动着数值处理流程。编写函数求区间[100,500]中所有的回文数,要求每行打印10个数。根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码。如果操作数是浮点数,在 C 语言中是不允许直接进行。的结果是 -1,因为 -7 除以 3 商为 -2,余数为 -1;注意:每一个数据输出格式为 printf("%4d", i);的结果是 1,因为 7 除以 -3 商为 -2,余数为 1。取余运算要求两个操作数必须是整数类型,包括。开始你的任务吧,祝你成功!
    52 1
    |
    2月前
    |
    存储 C语言 开发者
    【C语言】字符串操作函数详解
    这些字符串操作函数在C语言中提供了强大的功能,帮助开发者有效地处理字符串数据。通过对每个函数的详细讲解、示例代码和表格说明,可以更好地理解如何使用这些函数进行各种字符串操作。如果在实际编程中遇到特定的字符串处理需求,可以参考这些函数和示例,灵活运用。
    94 10
    |
    2月前
    |
    存储 程序员 C语言
    【C语言】文件操作函数详解
    C语言提供了一组标准库函数来处理文件操作,这些函数定义在 `<stdio.h>` 头文件中。文件操作包括文件的打开、读写、关闭以及文件属性的查询等。以下是常用文件操作函数的详细讲解,包括函数原型、参数说明、返回值说明、示例代码和表格汇总。
    69 9
    |
    2月前
    |
    C语言 开发者
    【C语言】数学函数详解
    在C语言中,数学函数是由标准库 `math.h` 提供的。使用这些函数时,需要包含 `#include <math.h>` 头文件。以下是一些常用的数学函数的详细讲解,包括函数原型、参数说明、返回值说明以及示例代码和表格汇总。
    64 6

    热门文章

    最新文章