一、设计思路
题目:可以答题并判断对错,最后显示做对几道题。
在原有的基础上,又拓展了答题模块。
在结构体中添加了answer属性,把输入的答案与正确答案比较,若相等则计数加一。
二、源代码
(1)四则运算3.cpp
// 四则运算3.cpp : Defines the entry point for the console application.
// 袁佩佩 信1201-1班 20122785 2015/3/18 #include "stdafx.h"
#include "iostream.h"
#include "stdlib.h"
#include "time.h"
#include "Caculation.h"
#include "iomanip.h" //*****判断回答是否正确*****
bool RightOrWrong(Caculation &Q,int answer)
{
if(Q.sign==)
{
Q.answer=Q.num1+Q.num2;
}
else if(Q.sign==)
{
Q.answer=Q.num1-Q.num2;
}
else if(Q.sign==)
{
Q.answer=Q.num1*Q.num2;
}
else
Q.answer=Q.num1/Q.num2;
if(answer==Q.answer)
return true;
else
return false;
}
//******重新生成算术题******
void ReBuild(Caculation &Q)
{
if(para[]==)
Q.sign=rand()%;
else
Q.sign=rand()%;
Q.num1=rand()%(para[]-para[]+)+para[];
Q.num2=rand()%(para[]-para[]+)+para[];
} //*****输出函数*****
void Display1(LinkC C,Caculation &Q)
{
int temp,count=; //count记录重新生成题目的次数
for(int i=;i<=para[];i++)
{
cout<<"("<<i<<")";
if(para[]==)
Q.sign=rand()%; //有乘除法
else
Q.sign=rand()%; //没有乘除法
Q.num1=rand()%(para[]-para[]+)+para[]; //随机的(下限~上限)以内的整数
Q.num2=rand()%(para[]-para[]+)+para[];
RB: ReBuild(Q); //检查是否有出过的题目
if(count>((para[]-para[]+)*(para[]-para[]+)*))
{
cout<<endl<<"该难度的题目已出完,请更改出题设置!"<<endl;
break;
}
switch(Q.sign)
{
case :
if(ExistQues(C,Q))
{
count++;
goto RB;
}
cout<<Q.num1<<"+"<<Q.num2<<"="<<setw();
break;
case :
if((para[]==)&&(Q.num1<Q.num2))
{ //若为负数,则交换
temp=Q.num1;
Q.num1=Q.num2;
Q.num2=temp;
}
if(ExistQues(C,Q))
{
count++;
goto RB;
}
cout<<Q.num1<<"-"<<Q.num2<<"="<<setw();break;
case :
if(ExistQues(C,Q))
{
count++;
goto RB;
}
cout<<Q.num1<<"*"<<Q.num2<<"="<<setw();break;
case :
while(Q.num2==)
Q.num2=rand()%(para[]-para[]+)+para[];
if(!para[])
{
while((Q.num1%Q.num2)!=||Q.num2==)
{ //重新生成
Q.num1=rand()%(para[]-para[]+)+para[];
Q.num2=rand()%(para[]-para[]+)+para[];
}
}
if(ExistQues(C,Q))
{
count++;
goto RB;
}
cout<<Q.num1<<"/"<<Q.num2<<"="<<setw();break;
}
InsertQues(C,Q);
if(i%para[]==) //一行打印完规定列数,换行
for(int j=;j<=para[];j++)
cout<<endl;
}
cout<<endl<<endl;
}
//*****回答题目函数******
void Display2(LinkC C,Caculation &Q)
{
int temp,count=,answer=,right=; //count记录重新生成题目的次数
for(int i=;i<=para[];i++)
{
cout<<"("<<i<<")";
if(para[]==)
Q.sign=rand()%; //有乘除法
else
Q.sign=rand()%; //没有乘除法
Q.num1=rand()%(para[]-para[]+)+para[]; //随机的(下限~上限)以内的整数
Q.num2=rand()%(para[]-para[]+)+para[];
RB: ReBuild(Q); //检查是否有出过的题目
if(count>((para[]-para[]+)*(para[]-para[]+)*))
{
cout<<endl<<"该难度的题目已出完,请更改出题设置!"<<endl;
break;
}
switch(Q.sign)
{
case :
if(ExistQues(C,Q))
{
count++;
goto RB;
}
cout<<Q.num1<<"+"<<Q.num2<<"=";
cin>>answer;
if(RightOrWrong(Q,answer))
{
cout<<"\t√";
right++;
}
else
cout<<"\t×";
break;
case :
if((para[]==)&&(Q.num1<Q.num2))
{ //若为负数,则交换
temp=Q.num1;
Q.num1=Q.num2;
Q.num2=temp;
}
if(ExistQues(C,Q))
{
count++;
goto RB;
}
cout<<Q.num1<<"-"<<Q.num2<<"=";
cin>>answer;
if(RightOrWrong(Q,answer))
{
cout<<"\t√";
right++;
}
else
cout<<"\t×";
break;
case :
if(ExistQues(C,Q))
{
count++;
goto RB;
}
cout<<Q.num1<<"*"<<Q.num2<<"=";
cin>>answer;
if(RightOrWrong(Q,answer))
{
cout<<"\t√";
right++;
}
cout<<"\t×";
break;
case :
while(Q.num2==)
Q.num2=rand()%(para[]-para[]+)+para[];
if(!para[])
{
while((Q.num1%Q.num2)!=||Q.num2==)
{ //重新生成
Q.num1=rand()%(para[]-para[]+)+para[];
Q.num2=rand()%(para[]-para[]+)+para[];
}
}
if(ExistQues(C,Q))
{
count++;
goto RB;
}
cout<<Q.num1<<"/"<<Q.num2<<"=";
cin>>answer;
if(RightOrWrong(Q,answer))
{
cout<<"\t√";
right++;
}
cout<<"\t×";
break;
}
InsertQues(C,Q);
cout<<endl;
}
cout<<"共回答正确"<<right<<"道题。";
cout<<endl<<endl;
} //*****判断难度*****
void YesOrNo(int para)
{
if(para)
cout<<"是";
else
cout<<"否";
}
//*****查看设置*****
void ShowSetting()
{
system("cls");
cout<<"\t/*************四则运算出题系统*************/"<<endl;
cout<<"\t题目数量:"<<para[]<<"个\t\t打印列数:"<<para[]<<"列"<<endl;
cout<<"\t每行间隔:"<<para[]<<"行\t\t是否有乘除法:";YesOrNo(para[]);cout<<endl;
cout<<"\t数值范围下限:"<<para[]<<"\t\t数值范围上限:"<<para[]<<endl;
cout<<"\t是否有负数:";YesOrNo(para[]);cout<<"\t\t是否有余数:";YesOrNo(para[]);cout<<endl;
cout<<"\t/******************************************/"<<endl;
}
//*****设置打印方式*****
void SetPrint()
{
system("cls");
char move1;
cout<<"\t/*************设置打印方式*************/"<<endl;
cout<<"\t 0.设置打印列数("<<para[]<<"列)"<<endl;
cout<<"\t 1.设置每行间隔("<<para[]<<"行)"<<endl;
cout<<"\t 2.返回主菜单"<<endl;
cout<<"\t/**************************************/"<<endl;
cout<<"请选择后续操作(0~2):";
cin>>move1;
while(move1<''||move1>'')
{
cout<<"错误!请正确输入操作序号(0~2):";
cin>>move1;
}
switch(move1)
{
case '':
reset2: cout<<"新的打印列数(建议7列以内):";
cin>>para[];
if(para[]<)
{
cout<<"出错!请重新输入!"<<endl;
goto reset2;
}
break;
case '':
reset3: cout<<"新的间隔行数:";
cin>>para[];
if(para[]<)
{
cout<<"出错!请重新输入!"<<endl;
goto reset3;
}
break;
case '':break;
}
}
//*****判断输入正确*****
void Reset(int i)
{
do
{
cout<<"请重新设置(是1/否0):";
cin>>para[i]; //此处输入字符出错,但没解决
}while(para[i]!=&¶[i]!=);
}
//*****设置题目难度*****
void SetLevel()
{
system("cls");
char move2;
cout<<"\t/*************设置题目难度*************/"<<endl;
cout<<"\t 0.是否有乘除法(";YesOrNo(para[]);cout<<")"<<endl;
cout<<"\t 1.数值范围("<<para[]<<"~"<<para[]<<")"<<endl;
cout<<"\t 2.是否有负数(";YesOrNo(para[]);cout<<")"<<endl;
cout<<"\t 3.是否有余数(";YesOrNo(para[]);cout<<")"<<endl;
cout<<"\t 4.返回主菜单"<<endl;
cout<<"\t/**************************************/"<<endl;
cout<<"请选择后续操作(0~4):";
cin>>move2;
while(move2<''||move2>'')
{
cout<<"错误!请正确输入操作序号(0~4):";
cin>>move2;
}
switch(move2)
{
case '':Reset();break;
case '': //此处若输入字符,则出错
reset1: cout<<"新的数值下限:"; //但没找到解决方法
cin>>para[];
cout<<"新的数值上限:";
cin>>para[];
if(para[]>=para[])
{
cout<<"出错!请重新输入数值范围!"<<endl;
goto reset1;
}
break;
case '':Reset();break;
case '':Reset();break;
case '':break;
}
}
//****主页面*****
void MainMenu(LinkC &C,Caculation &Q)
{
char move,save;
cout<<"\t/*************四则运算出题系统*************/"<<endl;
cout<<"\t 0.开始出题"<<endl;
cout<<"\t 1.设置出题数量"<<endl;
cout<<"\t 2.设置打印方式"<<endl;
cout<<"\t 3.设置题目难度"<<endl;
cout<<"\t 4.查看当前设置"<<endl;
cout<<"\t 5.开始答题"<<endl;
cout<<"\t 6.退出系统"<<endl;
cout<<"\t/******************************************/"<<endl;
cout<<"请选择后续操作(0~6):";
cin>>move;
while(move<''||move>'')
{
cout<<"错误!请正确输入操作序号(0~6):";
cin>>move;
}
switch(move)
{
case '':Display1(C,Q);break;
case '':
reset4: cout<<"请设置出题数量(建议100道以内):";
cin>>para[];
if(para[]<=)
{
cout<<"出错!请重新输入!"<<endl;
goto reset4;
}
break;
case '':SetPrint();break;
case '':SetLevel();break;
case '':ShowSetting();break;
case '':Display2(C,Q);break;
case '':
cout<<"是否保存出题记录(是1/否0):";
cin>>save;
while(save!=''&&save!='')
{
cout<<"出错!请正确输入(是1/否0):";
cin>>save;
}
if(save=='')
WriteQues(C);
cout<<"感谢您的使用,再见!"<<endl;
para[]=;break;
}
} int main(int argc, char* argv[])
{
srand((unsigned)time(NULL)); //srand()函数产生一个以当前时间开始的随机种子
LinkC Cacu;
Caculation ques;
InitList(Cacu);
ReadQues(Cacu);
while(para[])
{
system("cls");
MainMenu(Cacu,ques);
system("pause");
}
return ;
}
(2)Caculation.h
#include "iostream.h"
#include "fstream.h" //0退出、1出题数量、2打印列数、3每行间隔、4乘除、5数值范围下限、6数值范围上限、7负数、8余数、9出过的题目数
int para[]={,,,,,,,,,}; //默认参数 //*****四则算术题的数据结构*****
typedef struct
{
int num1;
int num2;
int sign;
int answer;
}Caculation;
typedef struct CNode //结点
{
Caculation ques;
struct CNode * next;
}CNode,*LinkC;
//******题目初始化******
void InitList(LinkC &C)
{
C=new CNode;
C->next=NULL;
}
//******添加题目信息******
void InsertQues(LinkC &C,Caculation Q)
{ //尾插入
LinkC tail,temp;
tail=C;
while(tail&&tail->next!=NULL)
tail=tail->next;
temp=new CNode;
temp->ques=Q;
temp->next=NULL;
tail->next=temp;
tail=temp;
para[]++;
}
//******判断题目存在******
int ExistQues(LinkC C,Caculation Q)
{
LinkC temp;
temp=C->next;
while(temp)
{
if((temp->ques.num1==Q.num1)&&(temp->ques.num2==Q.num2)&&(temp->ques.sign==Q.sign))
return ; //当两个数字和算符与链表中的一样,则存在
else
temp=temp->next;
}
return ;
}
//******读取出过的问题******
void ReadQues(LinkC &C)
{
LinkC temp;
ifstream infile("question.txt");
for(int i=;i<;i++) //读取参数表
infile>>para[i];
for(i=;i<para[];i++) //读取出过的题目
{
temp=new CNode;
infile>>temp->ques.num1;
infile>>temp->ques.num2;
infile>>temp->ques.sign;
temp->next=NULL;
}
}
//******写入文件******
void WriteQues(LinkC C)
{
LinkC temp;
ofstream outfile("question.txt");
if(!outfile)
{
cout<<"文件存储失败!"<<endl;
exit();
}
for(int i=;i<;i++)
outfile<<para[i]<<" ";
for(temp=C->next;temp;temp=temp->next)
{
outfile<<temp->ques.num1<<" ";
outfile<<temp->ques.num2<<" ";
outfile<<temp->ques.sign<<" ";
}
}
三、结果截图
四、心得体会
之所以选这一项,是因为这星期考研课开始了,周六日没有那么多的时间。而我的程序可拓展性好,添加功能比较容易,我就直接在原来的程序上进行了修改。
五、PSP0级
项目计划总结:
周活动总结表
姓名:袁佩佩 日期:3/19
日期 任务 |
听课 |
编写程序 |
阅读课本 |
准备考试 |
日总计 |
||
周日 |
|||||||
周一 |
300 |
300 |
|||||
周二 |
400 |
400 |
|||||
周三 |
100 |
148 |
248 |
||||
周四 |
300 |
300 |
|||||
周五 |
|||||||
周六 |
|||||||
周总结 |
阶段时间和效率 周数(上一次周活动表的周数+1):2
不包括上一周在内的累计时间
总计 |
1100 |
148 |
1248 |
||||
平均 |
1100 |
148 |
1248 |
||||
最大 |
1100 |
148 |
1248 |
||||
最小 |
1100 |
148 |
1248 |
以前各周的累计时间
总计 |
800 |
268 |
95 |
1163 |
|||
平均 |
800 |
268 |
95 |
1163 |
|||
最大 |
800 |
268 |
95 |
1163 |
|||
最小 |
800 |
268 |
95 |
1163 |
时间记录表:
学生 袁佩佩 日期 3/19
教师 王建民 课程 PSP
日期 |
开始时间 |
结束时间 |
中断时间 |
净时间 |
活动 |
备注 |
15/3/18 |
14:00 |
16:20 |
80 |
编写结对开发的作业 |
||
21:00 |
22:08 |
68 |
改写四则运算3 |
缺陷记录日志:
学生 袁佩佩
日期 3/19
教员 王建民
程序号 3
日期 |
编号 |
类型 |
引入阶段 |
排除阶段 |
修复时间 |
修复缺陷 |
3/18 |
1 |
编码 |
编译 |
2min |
||
描述:#define 时在最后加了分号 |
||||||
2 |
编码 |
执行 |
25min |
逻辑错误 |
||
描述:算法无法达到预期结果 |