一、需求分析
- 用一个结构体对题库进行储存
- 能够用文件保存题库并以结构体的形式保存题目
- 点击开始考试后用户可自己输入考试中的N道题目数量并从题库中随机抽取N道题目
- 用户能够通过键盘来实现自己输入自己的答案
- 系统以菜单的形式工作
- 程序执行的命令:
⑴ 创建结构体
⑵ 搜索题目
⑶ 输出题目
二、概要设计
⒈ 设计结构的抽象数据类型定义:
typedef struct que
{
char qst[200],A[100],B[100],C[100],D[100];
char key[200];
}que;
⒉ 答题系统的抽象数据类型定义:
iz();
初始条件:main()函数调用timu()
操作结果:计算题库中的题目数量n
初始条件:已经使用iz();计算题库中题目数量n,timu()调用menu();
操作结果:可以通过鼠标来选择开始答题start();、增加题目add();、退出系统leave();
初始条件:已经进入系统
操作结果:根据鼠标点击位置调用相应函数
start();
操作结果:开始答题并通过用户输入的题目数量来随机抽取题库中的题目
add();
操作结果:对题库中的题目进行增加
leave();
操作结果:离开系统
3.本程序模块框架
(1)主函数模块
Int main()
初始化;
接受命令;menu();
(2)结构体模块——实现对题目的储存与读取
(3)答题模块——实现用户自选题目数量并抽取试题
(4)分数模块——实现对用户答题完成后显示用户的分数
三、详细设计
1.
(1)主函数模块
#include "fun.h"
#include <iostream>
#include<stdio.h>
#include <graphics.h> // 引用ege图形库
#include <ege/sys_edit.h>
#include<string.h>
#include<time.h>
#include<stdlib.h>int main()
{
timu();
menu();
getch();
closegraph();
return 0;
}}
(2)框架模块
#include "fun.h"
#include <iostream>
#include<stdio.h>
#include <graphics.h> // 引用ege图形库
#include <ege/sys_edit.h>
#include<string.h>
#include<time.h>
#include<stdlib.h>
void initEditBox(sys_edit* editBox, int x, int y, int width, int height)
{
editBox->create(false);
editBox->size(width, height + 8);
editBox->setbgcolor(LIGHTBLUE);
editBox->setfont(24, 0, "黑体");
editBox->move(x, y);
editBox->visable(true);
editBox->setfocus();
editBox->create(false);
editBox->size(width, height + 8);
editBox->setbgcolor(LIGHTBLUE);
editBox->setfont(24, 0, "黑体");
editBox->move(x, y);
editBox->visable(true);
editBox->setfocus();
}
int main()
{
timu();
menu();
getch();
closegraph();
return 0;
}
void iz()
{
cleardevice();
initgraph(680,480,0);
PIMAGE p=newimage();
getimage(p,"C:\\Users\\26904\\Desktop\\KESHE\\IMG_20220303_191959.jpg");
putimage(0,0,p);;
setfont(40,20,"宋体");
setbkmode(TRANSPARENT);
rectprintf(100,100,400,160,"添加题目成功");
back();
}
//计算题库中的题目数量
void timu()
{
FILE* readf;
que ti;
readf=fopen("C:\\Users\\26904\\Desktop\\KESHE\\question.txt","r");
int num=0;
n=-1;
while(num!= EOF){
num=fscanf(readf,"%s %s %s %s %s %s\n",ti.qst,ti.A,ti.B,ti.C,ti.D,ti.key);
//读完第一行后,指针指向第二行
n++;
}
}
//主菜单
void menu()
{
cleardevice();
int x,y;
initgraph(1000, 600,0);
PIMAGE p=newimage();
getimage(p,"C:\\Users\\26904\\Desktop\\KESHE\\IMG_20220303_165507.jpg");
putimage(0,0,p);
setbkcolor(WHITE);
setfillcolor(LIGHTBLUE);
bar(300,110,700,200);
setfillcolor(LIGHTBLUE);
bar(300,220,700,310);
setfillcolor(LIGHTBLUE);
bar(300,330,700,420);
bar(200,500,850,550);
setcolor(BLACK);
setfont(50, 35, "宋体");
setbkmode(TRANSPARENT);
outtextxy(360,130, "开始答题");
outtextxy(360,240, "增加试题");
outtextxy(360,350, "退出系统");
setcolor(BLACK);
setfont(25, 20, "宋体");
xyprintf(200, 500, "当前题库数量为:%d",n);
outtextxy(180,60, "欢迎来到单项选择题标准化考试系统");
mouse_msg msg = {0};//声明一个保存鼠标消息的结构体
for ( ; is_run(); delay_fps(60))//is_run()判断窗口是否存在
{
while (mousemsg()) //等到鼠标消息
{
mousepos(&x, &y); //获取鼠标消息当前坐标点
msg = getmouse();//获取鼠标消息
if(msg.is_down()&&msg.is_left()&&300<x&&x<700&&110<y&&y<200)//左键按下
{
start();
}
if(msg.is_down()&&msg.is_left()&&300<x&&x<700&&220<y&&y<310)//左键按下
{
add();
}
if(msg.is_down()&&msg.is_left()&&300<x&&x<700&&330<y&&y<420)//左键按下
{
leave();
}
}
}
}
void back()
{
setfont(40,20,"宋体");
setfillcolor(LIGHTBLUE);
bar(0,0,80,40);
setbkmode(TRANSPARENT);
rectprintf(0,0,100,100,"返回");
mouse_msg msg = {0};//声明一个保存鼠标消息的结构体
for ( ; is_run(); delay_fps(60))//is_run()判断窗口是否存在,delay_fps(60)动画播放帧
{
while (mousemsg()) //等到鼠标消息
{
mousepos(&x, &y); //获取鼠标消息当前坐标点
msg = getmouse();//获取鼠标消息
if(msg.is_down()&&msg.is_left())//左键按下
if(x<=80&&y<=40)
menu();
}
}
}
//添加题目
void add()
{
cleardevice();
FILE* readf;
readf=fopen("C:\\Users\\26904\\Desktop\\KESHE\\question.txt","a");
initgraph(680,480, INIT_RENDERMANUAL);
setbkcolor(WHITE);
PIMAGE S=newimage();
getimage(S,"C:\\Users\\26904\\Desktop\\KESHE\\IMG_20220303_171813.jpg");
putimage(0,0,S);
sys_edit editBox[6];
int width = 280, height = 40;
char bb;
bb='A';
char text[64];
int i;
for (i = 1; i <5; i++)
{
int x = ((i+5) % 2) * 300 + 20, y = ((i+5) / 2) * 60 + 20;
initEditBox(&editBox[i], x, y, width, height);
sprintf(text, "%c.",bb);
bb++;
editBox[i].settext(text);
}
setbkmode(TRANSPARENT);
setfillcolor(WHITE);
setfont(40,20,"宋体");
rectprintf(10,100,80,120,"题目");
rectprintf(110,400,180,430,"答案");
setfont(40,20,"宋体");
setfillcolor(BLUE);
bar(0,0,80,40);
setbkmode(TRANSPARENT);
rectprintf(0,0,100,100,"取消");
setfillcolor(BLUE);
bar(500,420,680,480);
setbkmode(TRANSPARENT);
rectprintf(510,430,680,480,"完成");
initEditBox(&editBox[0], 100,100, 400,30);
initEditBox(&editBox[5], 200,400,300,30);
mouse_msg msg = {0};//声明一个保存鼠标消息的结构体
que hu;
const int buffSize0 = 100;
char strBuffer0[100] = "";
const int buffSize1 = 100;
char strBuffer1[100] = "";
const int buffSize2 = 100;
char strBuffer2[100] = "";
const int buffSize3 = 100;
char strBuffer3[100] = "";
const int buffSize4 = 100;
char strBuffer4[100] = "";
const int buffSize5 = 100;
char strBuffer5[100] = "";
for ( ; is_run(); delay_fps(60))//is_run()判断窗口是否存在,delay_fps(60)动画播放帧
{
mousepos(&x, &y); //获取鼠标消息当前坐标点
msg = getmouse();//获取鼠标消息
if(msg.is_down() && msg.is_left() && x>510 && y>430)//左键按下
{
editBox[0].gettext(buffSize0,hu.qst);
editBox[1].gettext(buffSize1,hu.A);
editBox[2].gettext(buffSize2,hu.B);
editBox[3].gettext(buffSize3,hu.C);
editBox[4].gettext(buffSize4,hu.D);
editBox[5].gettext(buffSize5,hu.key);
rectprintf(10,100,80,120,hu.qst);
fprintf(readf,"%s %s %s %s %s %s\n",hu.qst,hu.A,hu.B,hu.C,hu.D,hu.key);
fclose(readf);
n++;
for(int zw=0;zw<6;zw++)
{
editBox[zw].destory();
}
iz();
}
if(msg.is_down() && msg.is_left() && x<100 && y<100)
{
for(int zw=0;zw<6;zw++)
{
editBox[zw].destory();
}
menu();
}
}
}
//开始答题
void start()
{
int q=0,ii;
char an[200]={0};
memset(an,0,sizeof(char)*200);
que ti;
score=0;
initgraph(680,480,INIT_RENDERMANUAL);
setbkcolor(WHITE);
char str[100];
memset(str,0,sizeof(char)*100);
//调用对话框函数
inputbox_getline("请输入", "请输入正确的题目数量(回车确认)", str, 100);
int sum = 0;
const char* p = str;
for (p = str; *p != '\0'; p++)
{
sum = 10 * sum + (*p - '0');
}
int i,j,flag,x,a[sum]={0};//数组初始化为0
srand(GetTickCount());
x = rand()% n + 1;//生成 1~20 之间的随机数
a[0] = x;
for(i=1; i<sum; i++){//生成数组前n个随机数
x = rand()%n+1;
a[i] = x;
for(j=0; j<i; j++){//筛选有效随机数
if(a[i] == a[j]){//随机数重复,则随机数无效
i-=1;//随机数无效,数组下标减1,重新生成当前数组随机数
break;
}
}
}
for(i=0;i<sum;i++)
{
for(j=0;j<sum;j++)
{
if(a[i]<a[j])
{
x=a[i];
a[i]=a[j];
a[j]=x;
}
}
}
sys_edit editBox1[6];
int width = 280, height = 40;
for (int i = 1; i <5; i++)
{
int x = ((i+5) % 2) * 300 + 20, y = ((i+5) / 2) * 60 + 20;
initEditBox(&editBox1[i], x, y, width, height);
}
initEditBox(&editBox1[0], 100,100,550,40);
initEditBox(&editBox1[5], 200,400,100,40);
setfont(40,20,"宋体");
rectprintf(10,100,80,120,"题目");
rectprintf(30,400,180,430,"你的答案");
setfillcolor(YELLOW);
bar(500,420,680,480);
setbkmode(TRANSPARENT);
rectprintf(510,430,680,480,"下一题");
PIMAGE L=newimage();
getimage(L,"C:\\Users\\26904\\Desktop\\KESHE\\IMG_20220303_193126.jpg");
putimage(0,0,L);
PIMAGE S=newimage();
getimage(S,"C:\\Users\\26904\\Desktop\\KESHE\\-95859aa3a39bfed.jpg");
putimage(604,0,S);
char text[64];
int nb=0;
j=0;
FILE* readf;
readf=fopen("C:\\Users\\26904\\Desktop\\KESHE\\question.txt","r");
for(j=0;j<sum;j++)
{
i=0;
while(a[j]!=i)
{
fscanf(readf,"%s %s %s %s %s %s\n",ti.qst,ti.A,ti.B,ti.C,ti.D,ti.key);
i++;
}
const int buffSize5 = 100;
char strBuffer5[100] = "";
sprintf(text, "%s",ti.qst);
editBox1[0].settext(text);
sprintf(text, "%s",ti.A);
editBox1[1].settext(text);
sprintf(text, "%s",ti.B);
editBox1[2].settext(text);
sprintf(text, "%s",ti.C);
editBox1[3].settext(text);
sprintf(text, "%s",ti.D);
editBox1[4].settext(text);
mouse_msg msg = {0};//声明一个保存鼠标消息的结构体
ii=0;
for ( ; is_run()&&ii==0; delay_fps(60))//is_run()判断窗口是否存在,delay_fps(60)动画播放帧
{
while (mousemsg()) //等到鼠标消息
{
mousepos(&x, &y); //获取鼠标消息当前坐标点
msg = getmouse();//获取鼠标消息
if(msg.is_down()&&msg.is_left()&&x>510&&y>430)//左键按下
{
editBox1[5].gettext(buffSize5,an);
if((strcmp(an,ti.key)==0))
{
score++;
}
editBox1[0].settext("");
editBox1[1].settext("");
editBox1[2].settext("");
editBox1[3].settext("");
editBox1[4].settext("");
editBox1[5].settext("");
ii=1;
}
}
}
}
fclose(readf);
for(int zw=0;zw<6;zw++)
editBox1[zw].destory();
over();
}
//答题结束输出用户的考试分数
void over()
{
cleardevice();
initgraph(680,480,0);
PIMAGE L=newimage();
getimage(L,"C:\\Users\\26904\\Desktop\\KESHE\\IMG_20220303_164819.jpg");
putimage(0,0,L);
setfont(40,20,"宋体");
setbkmode(TRANSPARENT);
rectprintf(100,300,400,160,"考试结束你的分数是:%d",score);
back();
}
//离开系统
void leave()
{
closegraph();
}
四、调试分析
1.开始在引用文件做题库时以w方式打开导致数据全无,之后先用R打开储存全部数据然后再以W方式打开即可解决问题。
2.不能够跳出振循环
3.在跳转至下一个界面时没有用 cleardevice();清楚上一个界面导致闪退
4.在跳转至下一个函数时没有用editBox.destory();将输入框清除导致进入下一个函数后任会出现上一个函数的输入框
5.在填充背景图片时没有将单斜杠改成双斜杠使得无法读取文件
五、用户手册
1.本程序运行环境为Windows x64操作系统,执行文件为单项选择题考试系统.exe.
2.进入演示程序后,有明显的选项系统
例如:
开始考试
增加试题
退出系统
根据鼠标按键即可进入对应的系统
- 开始答题之后开始由用户输入的数值来随机抽取试题
- 抽取试题结束后进入答题界面
5.答题结束后系统自动给出用户的 分数
6.在游戏结束画面中玩家可以选择再来一局或者退出至主菜单