♻️ 资源
大小: 71.8MB
➡️ 资源下载: https://download.csdn.net/download/s1t16/87484792
https://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 测试
在制作过程中,每做完一个模块都进行测试,遇到比较复杂的问题,新建工程逐个测试(比如在随机数据无法正常显示时,先单独测试是否是随机数产生出现问题)
在测试过程中遇到较为困难的问题,通过不断尝试、网上求助和与同学讨论等方法进行解决。
部分测试结果图如下



