基于C语言开发的捕捉流星小游戏

♻️ 资源

大小: 71.8MB

➡️ 资源下载: https://download.csdn.net/download/s1t16/87484792https://download.csdn.net/download/s1t16/87484792

捕捉流星小游戏

1 需求分析

用 C 语言编写一个捕捉流星游戏程序,程序运行后,先输入用户名,输入的用户名显示在信息区;

点"开始"按钮,则游戏开始,流星从左往右移动;

初始时有 5 道数学题(数学题随机产生,且要求答案互不相同,每位数都是 10 以内的),8 条流星(流星的值互不相同,5 个是 5 道题的正确答案,另外 3 个是随机的),位置随机;

显示一道题,用户用鼠标点击流星,若作答正确,删除流星,删除此道数学题,显示下一道题,用户得 1 分,若没有做对减 1 分,其余不变;

小鱼从左往右游,到边界后,再从右边出来;

点"暂停/继续"按钮,游戏暂停,再点一次,游戏继续

点"刷新"按钮,刷新题目,增加五道新题,同时更新流星;(本想做成增加,但由于界面限制,最终决定为刷新)

点"退出"按钮,则结束游戏,并把玩家姓名和所得分数写入文件中。

1.1 功能需求

可以输入用户名;

控制区有开始,暂停/继续,刷新,退出按钮;

游戏区中显示流星和题目;

信息区中显示玩家名,动态显示得分;

点击开始按钮游戏才开始,之后开始按钮失效;

数学题随机产生,且答案互异,流星链表中的随机非答案也与已有数据互异;

答对加一分,删除流星和当天题目,答错减一分,题目不变。题目答完后需要刷新或退出;

点击刷新,刷新五道题目,更新流星;

点击退出,存档并退出;

1.2 数据需求

玩家链表中存有玩家姓名和分数,玩家姓名初始输入,分数动态储存;

通过函数建立题目和流星链表,题目链表中存有题目的两个数字、结果和计算符号,流星链表中存有流星初始位置信息,速度信息和所带数据;

1.3 界面需求

1.4 开发环境需求

VS2019

2 概要设计

2.1 主要数据结构

复制代码
# define WIDTH 740//长
# define HEIGHT 462//宽
# define GAME_HEIGHT (HEIGHT*5/6)//385 游戏界面宽

typedef struct 
{
	int x;
	int y;
}Location;

typedef struct node  // 流星链表
{
    int x, y,s;
    int  data;
    struct node* next;
}METEOR;

typedef struct wenti  //题目链表
{
    int num1;//第一个数 
    int num2;//第二个数
    char c;//加减乘除
    int result;//结果 
    struct wenti* next;
}TITLE;

typedef struct     //答题者链表
{
    TCHAR name[20];
    int score;
}USER;

2.2 程序总体结构

2.3 子模块设计

设置背景 Background();

设置按键 displayButton();

第一次检测鼠标 Mouse(user);

void start(USER user)//开始函数 作为点击开始到主体函数的媒介,同时传入一些基本变量;

TITLE *CreatTitle()//创建题目 创建题目链表

METEOR Creatmeteor(TITLET) //创建流星 创建流星链表

int checkButton(int mouseX, int mouseY)//检查按钮 检查鼠标是否点击按钮

void MIANbody(int i,IMAGE p,IMAGE temp,METEOR h,TITLET,USER user)//主体函数

主体函数实现该程序主要功能,包括流星移动,检测鼠标点击,动态计分,实现暂停刷新等,是本程序的核心函数;

void drawAlpha(IMAGE* picture, int picture_x, int picture_y) //x 为载入图片的 X 坐标,y 为 Y 坐标 实现图片背景透明化

3 详细设计

本程序的主要功能在主体函数中实现,具体如下(注意不是主函数)

复制代码
void MIANbody(int i,IMAGE *p,IMAGE *temp,METEOR *h,TITLE *T,USER user)//主体函数
{
    int j, a, w,jud,which;
    int mouseX;	        //鼠标位置坐标X
    int mouseY;
    int flag = 0;
    METEOR *k;
    k = h;
    MOUSEMSG mmsg;	    //鼠标消息变量
    LOGFONT f;
    TCHAR s[3],s1[3],data[3],sco[3];
    LOGFONT g;
    for (j = i; ; j++)
    {
        if (T == NULL)
        {
            while (1)
            {
                BeginBatchDraw();
                getimage(temp, 0, 0, 740, 462);
                gettextstyle(&g);
                g.lfHeight = 50;
                _tcscpy_s(g.lfFaceName, _T("黑体"));
                g.lfQuality = ANTIALIASED_QUALITY;
                settextstyle(&g);
                setcolor(YELLOW);
                outtextxy(120, 180, _T("答题结束,请刷新或退出"));
                EndBatchDraw();
                Sleep(10);//暂停毫秒
                putimage(0, 0, temp);
                if (MouseHit())
                {
                    mmsg = GetMouseMsg();
                    switch (mmsg.uMsg)
                    {
                    case WM_LBUTTONDOWN:
                        mouseX = mmsg.x;
                        mouseY = mmsg.y;    //取出鼠标x,y值

                        //鼠标在按钮区
                        if (mouseX > 0 && mouseX <= WIDTH / 2 && mouseY > GAME_HEIGHT&& mouseY <= HEIGHT)
                        {
                            flag = checkButton(mouseX, mouseY);
                        }
                        if (flag == 3)
                        {
                            T = CreatTitle();
                            h = Creatmeteor(T);
                            MIANbody(0, p, temp, h, T,user);
                        }
                        else if (flag == 4)   //退出并存档
                        {
                            FILE* fp;                             //写入文件
                            errno_t err;
                            err = _wfopen_s(&fp, TEXT("user.txt"), TEXT("a"));
                            fwprintf(fp, TEXT("\n%20s%10d"), user.name, user.score);
                            fclose(fp);
                            closegraph();
                            exit(1);
                        }                           
                    }
                }
            }
        }
          
        if (j > 740)
            j = 0;
        
        _stprintf_s(s,_T("%d"), T->num1);            //使int型可以正确显示,否则乱码
        _stprintf_s(s1, _T("%d"), T->num2);
        _stprintf_s(sco, _T("%d"),user.score);
       
        gettextstyle(&f);
        f.lfHeight = 20;
        _tcscpy_s(f.lfFaceName, _T("宋体"));
        f.lfQuality = ANTIALIASED_QUALITY;
        settextstyle(&f);
        setcolor(YELLOW);
        BeginBatchDraw();
        getimage(temp, 0, 0, 740, 462);
        for (a = 0; k != NULL; a++)
        {
            _stprintf_s(data, _T("%d"), k->data);
            if(k->x + j * k->s>=-200&& k->x + j * k->s<=600)
            drawAlpha(p, k->x + j * k->s, k->y);
            outtextxy(k->x + 165 + j * k->s, k->y + 16, data);
            k = k->next;

        }
        gettextstyle(&g);
        g.lfHeight = 30;
        _tcscpy_s(g.lfFaceName, _T("黑体"));
        g.lfQuality = ANTIALIASED_QUALITY;
        settextstyle(&g);
        setcolor(YELLOW);
        outtextxy(340, 20, s);
        outtextxy(383, 20, T->c);
        outtextxy(420, 20, s1);
        outtextxy(WIDTH / 2 + 260, GAME_HEIGHT + 23, sco);
        EndBatchDraw();
        Sleep(10);//暂停毫秒
        putimage(0, 0, temp);
        k = h;
        if (MouseHit())
        {
            mmsg = GetMouseMsg();
            switch (mmsg.uMsg)
            {
            case WM_LBUTTONDOWN:
                mouseX = mmsg.x;
                mouseY = mmsg.y;    //取出鼠标x,y值

                //鼠标在按钮区
                if (mouseX > 0 && mouseX <= WIDTH / 2 && mouseY > GAME_HEIGHT&& mouseY <= HEIGHT)
                {
                    flag = checkButton(mouseX, mouseY);
                }
                //鼠标点击流星
                else
                {
                    while(k!=NULL)
                    {
                        if (mouseX >= (k->x  + j * k->s) && mouseX <= (k->x + 220 + j * k->s) && mouseY >= (k->y) && mouseY <= (k->y + 50))
                        {
                            if (k->data == T->result)
                            {
                                T = T->next;
                                h = h->next;
                                user.score += 1;
                            }                              
                            else
                                user.score -= 1;
                            break;
                        }
                        else
                            k = k->next;
                    }
                    k = h;
                }

                if (flag == 2)  //暂停
                {
                    while (1)
                    {

                        gettextstyle(&f);
                        f.lfHeight = 20;
                        _tcscpy_s(f.lfFaceName, _T("宋体"));
                        f.lfQuality = ANTIALIASED_QUALITY;
                        f.lfQuality = ANTIALIASED_QUALITY;
                        settextstyle(&f);
                        setcolor(YELLOW);
                       BeginBatchDraw();
                        getimage(temp, 0, 0, 740, 462);
                        for (a = 0; k != NULL; a++)
                        {
                            _stprintf_s(data, _T("%d"), k->data);
                            if (k->x + j * k->s >= -200 && k->x + j * k->s <= 600)
                                drawAlpha(p, k->x + j * k->s, k->y);
                            outtextxy(k->x + 165 + j * k->s, k->y + 16, data);
                            k = k->next;

                        }
                        gettextstyle(&g);
                        g.lfHeight = 30;
                        _tcscpy_s(g.lfFaceName, _T("黑体"));
                        g.lfQuality = ANTIALIASED_QUALITY;
                        settextstyle(&g);
                        setcolor(YELLOW);
                        outtextxy(340, 20, s);
                        outtextxy(383, 20, T->c);
                        outtextxy(420, 20, s1);
                        outtextxy(WIDTH / 2 + 260, GAME_HEIGHT + 23, sco);
                        EndBatchDraw();
                        Sleep(10);//暂停毫秒
                        putimage(0, 0, temp);
                        k = h;
                        if (MouseHit())
                        {
                            mmsg = GetMouseMsg();
                            switch (mmsg.uMsg)
                            {
                            case WM_LBUTTONDOWN:
                                mouseX = mmsg.x;
                                mouseY = mmsg.y;    //取出鼠标x,y值

                                //鼠标在按钮区
                                if (mouseX > 0 && mouseX <= WIDTH / 2 && mouseY > GAME_HEIGHT&& mouseY <= HEIGHT)
                                {
                                    flag = checkButton(mouseX, mouseY);
                                }
                                if (flag == 2)
                                    MIANbody(j, p, temp, h, T,user);
                                if (flag == 4)
                                {
                                    FILE* fp;                             //写入文件
                                    errno_t err;
                                    err = _wfopen_s(&fp, TEXT("user.txt"), TEXT("a"));
                                    fwprintf(fp, TEXT("\n%20s%10d"), user.name, user.score);
                                    fclose(fp);
                                    closegraph();
                                    exit(1);
                                }
                            }
                        }
                    }
                }
                else if (flag == 3)            //增加流星,由于界面原因,在本作中其实是刷新题目
                {

                    T = CreatTitle();
                    h = Creatmeteor(T);
                    MIANbody(0, p, temp, h, T,user);
                }
                else if (flag == 4)         //退出并存档
                {
                    
                    FILE* fp;                             //写入文件
                    errno_t err;
                    err = _wfopen_s(&fp, TEXT("user.txt"), TEXT("a"));             
                    fwprintf(fp, TEXT("\n%20s%10d"), user.name, user.score);
                    fclose(fp);
                    closegraph();
                    exit(1);
                }
                
            }
        }
    }
}

4 测试

在制作过程中,每做完一个模块都进行测试,遇到比较复杂的问题,新建工程逐个测试(比如在随机数据无法正常显示时,先单独测试是否是随机数产生出现问题)

在测试过程中遇到较为困难的问题,通过不断尝试、网上求助和与同学讨论等方法进行解决。

部分测试结果图如下

相关推荐
C++ 老炮儿的技术栈8 小时前
C++ const 的3个核心作用
服务器·c语言·c++·算法·c
小黄人软件8 小时前
粘贴助手C++版 支持 Windows 7 / 10 / 11 不会出现缺少api-ms-win-core-path-11-1-0.dll
开发语言·c++·windows
半亩码田8 小时前
C#转Python第4.7篇:logging:Python 的标准日志库
开发语言·python·c#
程序员老陆8 小时前
从汇编层面理解 C++ 多线程
开发语言·c++·程序设计
谢亮_vipxieliang8 小时前
深入理解 JavaScript 数据类型与类型转换
开发语言·javascript·ecmascript
IOT-Power8 小时前
模板方法 + 策略模式
开发语言·c++
EatFan9 小时前
2026 Rust 后端技术栈选型:Axum 0.8 + Tokio + SQLx 全链路怎么搭
开发语言·后端·rust·tokio·serde·axum·sqlx
外收内放9 小时前
Python基础语法练习题(59-原始版本与优化版本)
开发语言·python
2401_888859719 小时前
STM32H733 MPU、AXI、FMC学习
java·开发语言·stm32·spring
泡海椒9 小时前
JQuick-Excel 实战:用 STYLE 配置单元格与区域样式
开发语言·python·excel