【程序设计实验报告(1)口算比赛】(中二版)

本文介绍了一个自动化的随机题目生成及评测系统的设计与实现,包括不同难度级别的题目生成算法、答案计算方法、学生答题流程及成绩评定机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 教师出题系统

//由于题目难度不同,要求生成的问题里的题目的数据以及符号的范围是不同的,(比如easy难度要求题目的数据是在1~9,符号限于加减)
//根据原始的老版本程序也就是old··question的生成数据和符号的方式,进行了优化,确保代码简便性
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
typedef struct problem
{
    int a;
    char x;
    int b;
}T;
typedef struct question
{
    int e;
    char X;
    int f;
    char y;
    int g;
    char Y;
    int h;
}P;
typedef struct xxxx
{   
    char x[10];
}K;
int ANSWER(int a,char x,int b)
{
    int n=0;
    if(x=='+')
    {
        n=a+b;
    }
    else if(x=='-')
    {
        n=a-b;
    }
    else if(x=='*')
    {
        n=a*b;
    }
    else if(x=='/')
    {
        n=a/b;
    }
    return n;
}
int main()
{
   FILE *question0;
   FILE *question1;
   FILE *question2;
   FILE *open0;
   FILE *open1;
   FILE *open2;
   FILE *A0;
   FILE *A1;
   FILE *A2;
   question0 = fopen("easy.txt","w");
   question1 = fopen("medium.txt","w");
   question2 = fopen("difficult.txt","w");
   open0 = fopen("easy.txt","r");
   open1 = fopen("medium.txt","r");
   open2 = fopen("difficult.txt","r");
   A0 = fopen("answer-easy.txt","w");
   A1 = fopen("answer-medium.txt","w");
   A2 = fopen("answer-difficult.txt","w");
   srand((unsigned)time(NULL));//播种,使得rand()函数在程序运行的每个时刻生成的随机数都是不同的
   int a,b,k,i,c,N;
   int v,j,f,l;
   int a0,a1;
   T Q[21];
   P U[21];
   K DIO[21],JO[21];
   char x;
   printf("************************************************************************\n");
   printf("********************  JO小鬼居然来挑战我DIO大人了  *********************\n");
   printf("************************************************************************\n");
   printf("********************  木大木大木大木大木大木大木大  ********************\n");
   printf("************************************************************************\n");
   printf("*****************************  来吧,展示  *****************************\n");
   printf("************************************************************************\n");
   printf("************************  The Torld 砸哇路多  **************************\n");
   printf("************************************************************************\n");
   //easy
   for(i=0;i<20;i++)
   {
      a=rand()%9+1;//rand()函数直接用了空函数,在这个文件中也没有定义【这样的目的是为了简便】,此后的time()函数也是一样,因为这是对于文件的调用,rand()函数和srand()函数都在头文件stdlib.h中声明了,而函数的实现在源文件中(具体是哪个我目前还不清楚(应该是stdlib.c文件(因为头文件叫stdlib.h,源文件应该是和它重名的),而且这个应该是C自带的源文件),但是一定是C自带的源文件(某.c文件,包含rand()和srand()函数的定义,所有的库函数都是这样的),因此直接用空函数就行,函数直接在源文件(stdlib.c文件)中就实现了【其实原理就是“文件包含”中的对于文件的引用,不过是引用的C自带的头文件罢了】
      b=rand()%9+1;
      k=rand()%2;//根据k的返回值来判定生成的是加号还是减号
      if(a<b)//也可以将内容都改成i--;continue;就是往前倒带
      {
         c=a;
         a=b;
         b=c;
      }
      fprintf(question0,"%d",a);
      switch(k)
      {
         case 0:
         fprintf(question0,"+");
         x='+';
         break;
         case 1:
         fprintf(question0,"-");
         x='-';
         break;
      }
      fprintf(question0,"%d\n",b);
      a0=ANSWER(a,x,b);
      fprintf(A0,"%d\n",a0);
   }

//medium
    for(i=0;i<20;i++)
   {
      char m;
      a=rand()%100+1;
      b=rand()%100+1;
      k=rand()%4;
      switch(k)//根据k的返回值来判定生成哪种运算符
      {
         case 0:
         m='+';
         break;
         case 1:
         m='-';
         break;
         case 2:
         m='*';
         break;
         case 3:
         m='/';
         break;
      }
   int w=ANSWER(a,m,b);
      if(w<0||w>100)
      {
         i--;
         continue;
      }
      fprintf(question1,"%d",a);
      fprintf(question1,"%c",m);
      fprintf(question1,"%d\n",b);
      a1=ANSWER(a,m,b);
      fprintf(A1,"%d\n",a1);
   }  

//difficult
for(i=0;i<20;i++)
   {
      int q=0,c,d;
      a=rand()%9+1;
      b=rand()%9+1;
      c=rand()%9+1;
      d=rand()%9+1;
      k=rand()%4;
      if(a%b==0||c%d==0)
      {
         i--;
         continue;
      }
      if(a/b-c/d<0)
      {
         i--;
         continue;
      }
      else if(b%a==0)
      {
         b/=a;
         a=1;
         fprintf(question2,"%d",a);
         fprintf(question2,"/");
         fprintf(question2,"%d",b);
      }
      else if(a%b!=0&&b%a!=0)
      {
            for(q=2;q<10;q++)
         {
            if(a%q==0&&b%q==0)
            {
               a/=q;
               b/=q;
            }
         }
         fprintf(question2,"%d",a);
         fprintf(question2,"/");
         fprintf(question2,"%d",b); 
      } 
      switch(k)//根据k的返回值来判定生成哪种运算符
      {
         case 0:
         fprintf(question2,"+");
         x='+';
         break;
         case 1:
         fprintf(question2,"-");
         x='-';
         break;
         case 2:
         fprintf(question2,"*");
         x='*';
         break;
         case 3:
         fprintf(question2,"/");
         x='/';
         break;
      }
      if(d%c==0)
      {
         d/=c;
         c=1;
         fprintf(question2,"%d",c);
         fprintf(question2,"/");
         fprintf(question2,"%d\n",d);
      }
      else if(c%d!=0&&d%c!=0)
      {
         for(q=2;q<10;q++)
         {
            if(c%q==0&&d%q==0)
            {
               c/=q;
               d/=q;
            }
         }
         fprintf(question2,"%d",c);
         fprintf(question2,"/");
         fprintf(question2,"%d\n",d);
      }
      if(x=='+')
      {
         v=a*d;
         j=c*b;
         f=b*d;
         l=v+j;
         if(l%k==0)
         {
            fprintf(A2,"%d\n",l/f);
         }
         else if(f%l==0)
         {
            fprintf(A2,"1");
            fprintf(A2,"/");
            fprintf(A2,"%d\n",k/l);
         }
         else if(l%f!=0&&f%l!=0)
         {
            for(int NN=2;NN<10;NN++)
            {
               if(l%NN==0&&f%NN==0)
               {
                  l/=NN;
                  f/=NN;
               }
            }
            fprintf(A2,"%d",l);
            fprintf(A2,"/");
            fprintf(A2,"%d\n",f);
         }
      }
      else if(x=='-')
      {
         v=a*d;
         j=c*b;
         f=b*d;
         l=v-j;
         if(l%f==0)
         {
            fprintf(A2,"%d\n",l/f);
         }
         else if(f%l==0)
         {
            fprintf(A2,"1");
            fprintf(A2,"/");
            fprintf(A2,"%d\n",f/l);
         }
         else if(l%f!=0&&f%l!=0)
         {
            for(int NN=2;NN<10;NN++)
            {
               if(l%NN==0&&f%NN==0)
               {
                  l/=NN;
                  f/=NN;
               } 
            }
            fprintf(A2,"%d",l);
            fprintf(A2,"/");
            fprintf(A2,"%d\n",f);
         }
      }
      else if(x=='*')
      {
         l=a*b;
         f=c*d;
         if(l%f==0)
         {
            fprintf(A2,"%d\n",l/f);
         }
         else if(f%l==0)
         {
            fprintf(A2,"1");
            fprintf(A2,"/");
            fprintf(A2,"%d\n",f/l);
         }
         else if(l%f!=0&&f%l!=0)
         {
            for(int NN=2;NN<10;NN++)
            {
               if(l%NN==0&&f%NN==0)
               {
                  l/=NN;
                  f/=NN;
               } 
            }
            fprintf(A2,"%d",l);
            fprintf(A2,"/");
            fprintf(A2,"%d\n",f);
         }
      }
      else if(x=='/')
      {
         l=a*d;
         f=b*c;
         if(l%f==0)
         {
            fprintf(A2,"%d\n",l/f);
            }
         else if(f%l==0)
         {
            fprintf(A2,"1");
            fprintf(A2,"/");
            fprintf(A2,"%d\n",f/l);
         }
         else if(l%f!=0&&f%l!=0)
         {
            for(int NN=2;NN<10;NN++)
            {
               if(l%NN==0&&f%NN==0)
               {
                  l/=NN;
                  f/=NN;
               } 
            }
            fprintf(A2,"%d",l);
            fprintf(A2,"/");
            fprintf(A2,"%d\n",k);
         }
      }
   }
   fclose(question0);
   fclose(question1);
   fclose(question2);
   fclose(open0);
   fclose(open1);
   fclose(open2);
   fclose(A0);
   fclose(A1);
   fclose(A2);
   return 0;
} 

学生做题系统

#include<stdio.h>
#include<time.h>
typedef struct problem
{
    int a;
    char x;
    int b;
}T;
typedef struct question
{
    int e;
    char X;
    int f;
    char y;
    int g;
    char Y;
    int h;
}P;
typedef struct xxxx
{   
    char x[10];
}K;
int ANSWER(int a,char x,int b)
{
    int n=0;
    if(x=='+')
    {
        n=a+b;
    }
    else if(x=='-')
    {
        n=a-b;
    }
    else if(x=='*')
    {
        n=a*b;
    }
    else if(x=='/')
    {
        n=a/b;
    }
    return n;
}
int main()
{
    FILE *open0;
    FILE *open1;
    FILE *open2;
    FILE *A0;
    FILE *A1;
    FILE *A2;
    open0 = fopen("easy.txt","r");
    open1 = fopen("medium.txt","r");
    open2 = fopen("difficult.txt","r");
    A0 = fopen("answer-easy.txt","r");
    A1 = fopen("answer-medium.txt","r");
    A2 = fopen("answer-difficult.txt","r");
    T Q[21];
    P U[21];
    K DIODIO[21],JOJO[21];
    printf("************************************************************************\n");
    printf("***** 欢迎你,乔斯达血脉的人啊,看来你已经展示了你背后的星星印记了 *****\n");
    printf("************************************************************************\n");
    printf("***********************  那么前来挑战我DIO吧  **************************\n");
    printf("************************************************************************\n");
    printf("***********************  选择你的难度吧JOJO  ***************************\n");
    printf("************************************************************************\n");
    printf("************************  选择“简单”输入“0”  ***************************\n");
    printf("************************************************************************\n");
    printf("************************  选择“中等”输入“1”  ***************************\n");
    printf("************************************************************************\n");
    printf("************************  选择“困难”输入“2”  ***************************\n");
    printf("************************************************************************\n");
    int difficulty;
    int JO[21]={0},DIO[21]={10};
    int N,MISSDA=0;
    char W[10];
    scanf("%d",&difficulty);
    printf("************************  赛高泥high铁鸭子哒  **************************\n");
    printf("***************************  让我们开始吧  *****************************\n");
    time_t start,end;
    start=time(NULL);
    if(difficulty==0)
    {
        for(N=0;N<20;N++)
        {
            fscanf(open0,"%d",&Q[N].a);
            fscanf(open0,"%c",&Q[N].x);
            fscanf(open0,"%d",&Q[N].b);
            printf("%d",Q[N].a);
            printf("%c",Q[N].x);
            printf("%d\n",Q[N].b);
            printf("回答吧,食堂泼辣酱\n");
            scanf("%d",&DIO[N]);
        }
    }
    else if (difficulty==1)
    {
        for(N=0;N<20;N++)
        {
            fscanf(open1,"%d",&Q[N].a);
            fscanf(open1,"%c",&Q[N].x);
            fscanf(open1,"%d",&Q[N].b);
            printf("%d",Q[N].a);
            printf("%c",Q[N].x);
            printf("%d\n",Q[N].b);
            printf("回答吧,食堂泼辣酱\n");
            scanf("%d",&DIO[N]);
        }
    }
    else if (difficulty==2)
    {
        for(N=0;N<20;N++)
        {
            fscanf(open2,"%d",&U[N].e);
            fscanf(open2,"%c",&U[N].X);
            fscanf(open2,"%d",&U[N].f);
            fscanf(open2,"%c",&U[N].y);
            fscanf(open2,"%d",&U[N].g);
            fscanf(open2,"%c",&U[N].Y);
            fscanf(open2,"%d",&U[N].h);
            printf("%d",U[N].e);
            printf("%c",U[N].X);
            printf("%d",U[N].f);
            printf("%c",U[N].y);
            printf("%d",U[N].g);
            printf("%c",U[N].Y);
            printf("%d\n",U[N].h);
            printf("回答吧,食堂泼辣酱\n");
            scanf("%s",DIODIO[N].x);
        }
    }
    end=time(NULL);
    FILE *fp = NULL;
    time_t timep;
    struct tm *p;
    char name[256] = {0},g[10]={0};
    time(&timep);//获取从1970至今过了多少秒,存入time_t类型的timep
    p = localtime(&timep);//用localtime将秒数转化为struct tm结构体
    sprintf(name, "%d.%d.%d %d:%02d.txt",1900+p->tm_year,1+p->tm_mon,p->tm_mday,p->tm_hour,p->tm_min);//把格式化的时间写入字符数组中
    if((fp = fopen(name, "w")) == NULL)
        perror("");
    for(N=0;N<20;N++)
    {
        if(difficulty==0)
        {
            fprintf(fp,"%d\n",DIO[N]);
            fscanf(A0,"%d",&JO[N]);
            if(JO[N]==DIO[N])
            {
                MISSDA+=5;
            }
        }
        if(difficulty==1)
        {
            fprintf(fp,"%d\n",DIO[N]);
            fscanf(A1,"%d",&JO[N]);
            if(JO[N]==DIO[N])
            {
                MISSDA+=5;
            }
        }
        if(difficulty==2)
        {
            fprintf(fp,"%s\n",DIODIO[N].x);
            fscanf(A2,"%s",JOJO[N].x);
            if(JOJO[N].x==DIODIO[N].x)
            {
                MISSDA+=5;
            }
        }
    }
    int H=difftime(end,start);
    fprintf(fp,"******* 在你解答的时间里,我的砸瓦鲁多时间过了 %d 秒 *******\n",H);
    fprintf(fp,"************** 你的绿宝石水花居然得了 %d 分 **************\n",MISSDA);
    fprintf(fp,"********************** 咱就是说 **********************\n");
    fprintf(fp,"************************ 虽然 ***********************\n");
    fprintf(fp,"************** 我不记得我吃了多少片小面包 **************\n");
    fprintf(fp,"************** 但是老东西你的替身最没用啦 **************\n");
    fprintf(fp,"***************** 赛高泥high铁鸭子哒 *****************\n");
    fclose(open0);
    fclose(open1);
    fclose(open2);
    fclose(A0);
    fclose(A1);
    fclose(A2);
    return 0;
}

(用适当的形式表达算法设计思想与算法实现步骤)

实验大致分为四个模块:

教师出题

主要任务是针对三种难度的题目分别按照要求进行随机出题并写入到相应的难度的题库txt文件中。该过程使用rand函数生成随机数,使用srand结合时间函数进行播种,使得在不同时刻rand生成不同的随机数,达到了随机出题的效果。将随机数取4的余数,可以借此得到四种结果(0、1、2、3),对应加减乘除。

系统生成标准答案题库

主要任务是针对不同难度的题目进行计算给出标准答案并写入答案txt文件中。在easy和medium难度中都遵循“整形”“字符”“整形”的结构,故利用结构体数组从题库txt文件中读取文件,经过计算器函数计算,再将结果按照数组形式写入答案txt文件即可。difficult遵循“整形”“字符”“整形”“字符”“整形”“字符”“整形”的结构体,用该结构体实现读取题库txt文件之后,分为加减和乘除两大类,利用不同的计算方法计算完之后,再进行化简,最后按照结构仅为字符串数组的结构体的形式写入答案txt题库即可。

学生做题

首先在选定难度之后每次在学生给出答案之前依次以字符串的形式从相应的题库中出示一道题目,学生给出答案,并将每题的答案以字符串的形式储存到结构体数组中,当学生作答完所有题目之后,即刻将结构体数组中的每个结构体字符串依次写入答题纸txt文件,并以当前时刻命名。

评审阶段

利用time.h头文件里的time_t函数进行计时,从学生选择完难度开始,记时开始。学生答完第二十道题,计时结束,在将答案写入答题纸txt文件之后,将时长写入答题纸txt文件最后一行。将第三步中的答案结构体数组字符串依次与答案库中的标准答案对应,对一题加五分,将最后得分统计在答题纸txt文件中的最后一行。

(详细记录在调试过程中出现的问题及解决方法。记录实验执行的结果)

实验结果

 

 

 

(对实验结果进行分析,问题回答,实验心得体会及改进意见)

问题1:

如何生成随机题目

其本质就是生成随机数

解决方法:从《C primer plus》中学习   

该过程使用rand函数生成随机数,使用srand结合时间函数进行播种,使得在不同时刻rand生成不同的随机数,达到了随机出题的效果。

问题2:

如何随机生成符合要求的数据(数字和符号)

根据easy难度的题目要求,生成的题目的操作数要小于10大于0,那么就让随机数取9的模,得到的是0~8,然后加一,就得到1~9;在随机生成符号时,让随机数取2的模,得到两种答案,0或1,若为0,则生成减号,为1则生成加号。

在medium难度里,同理,让第一个操作数为随机数取101的模生成1~100,让第二个操作数为随机数取100的模,生成0~99,加一,生成1~100,即保证了a、b都在区间[0,100],又保证了当生成的式子是除法式子的时候分母b一定不是0。让随机数取4的模,得到0~3四个答案,分别对应加减乘除(switch语句(其他选择语句也可))。

在difficult难度里,要保证分式是化简后的切不能在化简后直接成整数,于是分别进行判断,如果分子能被分母整除,则说明化简后是整数,这个数据应该丢弃,那么就让循环数i--,然后用continue跳过这次循环,实现倒带;如果分母能被分子整除,分子就变成了1,分母变成了商;如果上述都不成立,就看分子分母有没有最小公倍数,调用一个从2到9的循环,如果存在最小非零非一公约数则分子分母同除最小非零非一公约数,然后继续循环,直到不存在公约数,此时化简完成。

同时,若生成的随机数不符合题目要求,则将循环数减一并执行continue,实现向前倒带,重新生成随机数,直到生成的符合要求。

问题3:

如何计时

利用time.h头文件里的time_t函数进行计时,从学生选择完难度开始,记时开始。学生答完第二十道题,计时结束,在将答案写入答题纸txt文件之后,将时长写入答题纸txt文件最后一行。将第三步中的答案结构体数组字符串依次与答案库中的标准答案对应,对一题加五分,将最后得分统计在答题纸txt文件中的最后一行。

问题4: 

如何以现在时刻命名并生成文件夹

命名主要使用time.h头文件中的time_t函数,计算从timep(1970至今)开始经过了多少秒,再使用localtime将其转化为struct tm结构体,用结构体指针将结构体内相对应的年月日时分写入文件名中即可。

总结心得:

我从这个实验中学习到的,

一是对于文件使用的进一步强化,二是认识并学习了time()函数、伪随机数函数rand(),通过播种并结合时间函数的随机数函数srand,以及利用取模的方式获得想要的随机数以及字符,拓宽了思路,具有启发性

此为源码(python):开发用于小学生口算练习的小程序,适合python初学者参考。如有不足请多指正!之前上传的资料没看过评论,很多朋友遇到了问题没有及时发现沟通解决,这次末尾有联系方式,有问题的朋友可以联系交流。 详细信息如下: 一、附件为小学生口算练习小程序,为自家宝贝设计的,自用之余拿来大家分享使用,非常适合一、二、三年级的小朋友。 二、程序功能: 1、生成任意数以内的+-*/单一或混合运算的口算卡(excel文件,可打印),每张80道题。 2、任意数以内的+-*/单一或混合运算的练习(练习前选择条件),显示答题总数、正确与错误数、用时及平均时间。 3、表内乘法口算练习(同2可以显示答题信息)。 4、生成表内乘法口诀练习口算卡,格式同1。 5、生成几乘几以上的专项表内乘法口诀练习口算卡,格式同1。 6、表内除法口算练习(同2可以显示答题信息)。 7、每日口算打卡练习,每日出题80道,在程序中答题,显示答题总数、正确与错误数、用时及平均时间。并且会将每次答题信息记录至程序目录中的一个excel文件中,跟踪小朋友的口算情况。 三、程序为exe程序(一个exe文件和一个excel模板文件,要在一个文件夹就可以),下载后无需安装直接可以运行,并且有excel模板,如果生成的excel文件打印出线或打印不全的,可以自行调整一下模板excel文件的列宽和行高,切记:模板文件建议不要插入或删除行或列,以免错乱。 四、附件为压缩文件(使用7Z程序压缩的),可以用winrar、360、好压 等解压,如有问题可以QQ(1064386744)或邮箱、微信联系解决。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值