【软件工程——结对项目】 “项目2:四则运算题目生成”

在这次分组中,我承担了界面制作的任务,以下所有内容皆为通过软件界面的角度进行书写,而生成题目等的具体内容请戳这里。↓↓↓↓↓↓↓↓
https://blog.csdn.net/qq_36965871

↑↑↑↑↑↑↑↑↑队友的博客

一、Github的地址

https://github.com/Crysflair/se-group-project-arithmetic

二、PSP 表格

PSP2.1Personal Software Process Stages预估耗时 (分钟)实际耗时(分钟)
Planning计划2535
· Estimate· 估计这个任务需要多少时间22073127
Development开发18822672
· Analysis· 需求分析(包括学习新技术)6047
· Design Spec· 生成设计文档3035
· Design Review· 设计复审(和同事审核设计文档)2035
· Coding Standard· 代码规范(为目前的开发制定合适的规范)1015
· Design· 具体设计6072
· Coding· 具体编码11301920
· Code Review· 代码复审172156
· Test· 测试(自我测试,修改代码,提交修改)400392
Reporting报告300420
· Test Report· 测试报告150200
· Size Measurement· 计算工作量50100
· Postmortem & Process Improvement Plan· 事后总结,并提出过程改进计划100120
-合计33623185

三、C# 面向用户的界面设计

▶ 思路描述

1)需求分析:

这次在进行需求分析之前,先说明一下我们组的选择。这里我们做的是 “项目2:四则运算题目生成” ,我们的扩展方向是把程序变成一个Windows电脑图形界面的程序,包括倒计时功能与历史记录功能。

  • 通过阅读文件说明,总结出以下需要实现的几个功能。
    出题:
  • 首先,需要给用户提供 出现在题目中的运算符号的选择功能;eg.只想进行加减运算,就只勾选“加法运算”和“减法运算”。
  • 其次,应提供自定义符号的显示方式;该功能不但包含了老师文件中要求的乘方符号要有^和 * *两种表达方式,而且还支持用户所能接受的任何的表达形式,包括中文字符。
  • 然后,选择真分数出现比例的功能;即表明软件支持真分数运算,且根据用户自定义,包含真分数的题目以用户定义的比例出现在题目中。
  • 输入包含运算符的最大个数;按照老师文件的要求,限制该最大个数为10个,用户定一的运算符个数应小于10个。
  • 输入运算范围功能;用户根据需求设定参与运算数的上下界。
  • 输入出题数目;用户根据小学生的实际情况自定义出题数目。根据文件要求,题目不得多于1000道。
  • 确认按键;表示上述设定的完成,接下来进入做题。
    做题:
  • 切题功能;在想进入下一题时通过某种操作(这里使用回车)进入下一题的做题状态中。
  • 进度条功能;显示跟做题者做题的进度。
  • 倒计时功能;当出题完成点击确认后,计时开始,根据要求限定为20秒倒计时。
  • 查看结算功能;当做完所有题后,点击提交按钮,出现成绩结算。
    评判:
  • 判题功能;将用户输入的答案和正确答案进行比对,如果错误则判错。
  • 输入接收功能;可能用户数输入的答案是对的,但是不符合正确答案的格式要求。eg.采用中文符号,多输入了空格等。
  • 错题响应功能;对做错的题目,系统发出bee声,以表明刚过去的那道题目做错了。
    历史记录:
  • 本次历史记录功能;保存该次做题的正确率,和做错的题目。点击历史记录按钮便可查看。
  • 历次历史记录功能;展示用户所有错的题目。
  • 历次里及时记录清除功能:点击清除,清除所有历史记录。
    出错处理:
  • 空白报错功能;对于没有输入相应信息的文本框,系统将进行提示和报错。
  • 超额报错功能;有的在出题模块内输入值超过范围,系统将进行报错和提示。
  • 不规范操作;如在做题过程中封锁对其他所有按键的操作,点击则提醒用户专心答题。
  • 时间结束处理;时间用尽但没有写题时,直接切题且本题目记为0分算作错题。

2) 思考过程:

在进行了需求分析之后,我总结出了比较难攻克的几个功能,一个是出错处理,一个是历史记录。所以先来说说这两块的功能。

对于出错处理重点是要考虑到用户所有可能产生的情况,对每一个错误地操作都要有报错提醒,而且互相不能搅乱整个软件的运行秩序。这里我们要始终坚信,用户是笨的,用户是懒的。任何一个可能存在的操作,都有可能使我们的软件质量得不到保障。而且这些错误很有可能是我在需求分析中未考虑到的情况。
这里我采取分阶段完善处理方法,共分为①需求分析阶段②编码阶段③测试阶段三个阶段,在每一个阶段都进行报错处理的完善。

  • 第一阶段,按照需求分析逐一攻破其中的内容,对于空白报错功能和超额报错功能,这里使用C#中提供的errorProvider控件,在相应文本框后设置报错感叹号且有错误提示。对于不规范操作,设置bool型变量,锁定相应的按键。对于时间结束处理,当时间为零时重置时间和题目,并用MessageBox发出错误消息。这一阶段的主要任务就是满足需求分析中提出的所有功能,并且每一个都要测试而且要测试成功。
  • 第二阶段,在编码过程中发现的还需增加报错处理的地方记录下来,最后进行增加。这里最后进行增加的原因是,有可能出现在编完后发现该报错不重要了,或存在变动。这一阶段的主要任务是对第一阶段的完善。
  • 第三阶段,交给同组成员进行测试,根据自己的尝试和他人的不断尝试,完善整个软件报错系统的不足之处。这一阶段的主要任务是尽最大的可能找出所有或接近所有的需要报错处理的地方进行增加修改。

以上具体实现和遇到的状况将在后续阐述。

对于历史记录重点是历史信息要存放在一个不易破坏的地方,每次写入都不能覆盖上一次写入的情况。如果没有点击清空按键,用户可以随时看到历史记录中的错题内容(做题时看不了)。居于以上考虑我打算采用文件存取的方式。第一次点击提交的时候,创建文件(使用相对路径),每个错误信息写在文件中保存,若无错题不用写文件,若有错题,写文件同时要接着文件尾写,防止覆盖文件,写完关闭文件。清除历史记录就相当于清除文件内容。

对于出题,则在界面设置相应文本框,只有判断出用户填写的信息准确无误时,才能真正点击确定按钮进入做题界面。

对于做题,出的题目由Generate()函数求得,该接口的提供在上方连接中的博客会有介绍,同时答案也是附带的。将出题的文本框设置成只读形式,防止用户随意更改。在做题文本框中判断是否有输入并且点击了回车,若满足条件,则进入评判记录。直到题目全部做完,提交后才能看到结算结果。

对于评判,展示之前记录的总做题数、正确题目数和正确率。由于分数不好确定,比如说有三道题时,分数不好分配,因此这里我们采用正确率。

3) 找资料过程:

在此次项目过程中,我查阅了许多有关C#的编程知识,C#算是我从未接触的语言,这次我算是边学边写,虽然有时候还是面向过程的思想,在错了又错的编码过程中,也是不断熟悉和纠正了自己的思维方式。微软网站上的C#指南给了我很多启示和指导,使我受益匪浅。

▶ 设计实现过程

1)窗体界面

  • 主界面
    在这里插入图片描述
  • 结算界面
    在这里插入图片描述
  • 历史记录界面
    在这里插入图片描述

2)功能测试

1.空白报错处理
遍历了所有的文本框分别空着的情况。下图为显示符号栏空着的情况,且为做过一次后再次出题的情况。
在这里插入图片描述
2.超额报错处理
遍历了所有超范围输入的情况处理。下图为输入运算符个数超过范围10。
在这里插入图片描述
3.不规范操作
遍历了所有按键的使用情况。下图为在做题时点击提交。
在这里插入图片描述
4.时间结束处理
分别在做题过程中,和最后一道题时等待时间用尽,查看系统处理效果。下图为在做题过程中时间用尽。
在这里插入图片描述
5.做题过程
输入正常情况内的出题值,模拟做题过程,观察有无差错。下图为做题过程中。
在这里插入图片描述
6.结算查看
观察判断结算的正确性,检查有无漏算现象,对于最后一题时间用尽后再写正确答案是否有效等。下图为有对有错的情况。
在这里插入图片描述
7.历史记录查看
检查历史记录是否保存的当,连续做题后以前的记录是否还在。下图为多次做题后查看历史记录。
在这里插入图片描述
8.清空历史记录
点击清空历史记录观察是否执行了相应功能,下图为点击清空历史记录后。
在这里插入图片描述
9.做题输入框不规范操作
在不是做题的时候,对输入文本框进行写或者回车操作将报错。下图为不在做题过程中,写文本框。
在这里插入图片描述
10.帮助按键
遍历所有文本框按下F1按键,观察有无提示信息。下图为选中除号文本框按下F1键。
在这里插入图片描述

3)改进

首先最需要改进的地方就是报错处理。在进行完了第一阶段①需求分析的功能实现后,在第二第三阶段还发现了遗漏的报错处理;其次改进了一些界面内容,使得整体操作清晰化,全面化;最后进行了美观美化。下面将一一列举改进了的地方。

  • 做题时的不必要操作。在做题的时候,我们默认小学生只能进行写题,切换下一题的操作权力,在最后一题答完时,才能获得提交的权利,在此之前的整个做题过程中,小学生不能有效的查看历史记录,不能有效的点击确认按钮(出题的)。
  • 对输入文本框过多的操作。在结束答题或不在答题状态时,对文本框进行编辑或者回车操作,则报错。在没有这项功能的时候,软件会将此类操作当成正常做题来处理,为此会出现数组溢出等故障。该遗漏在第三阶段被发现。
  • 清除历史记录的迅速程度。一开始,清除历史记录未删除文件内容操作,需要刷新才能体现空白页面,不符合平时逻辑,这里增加空信息赋予,使得记录看起来是迅速清空的。
  • 增加历史记录的随时记录性。在第三阶段发现只有当查看历史记录时,错题才会被记录,使得没有及时查看错题的记录丢失了,在挪动了代码的相应位置后,使得随时记录历史错题,且不会产生遗漏。
  • 修改历史记录文本框的可读性。为了防止小学生用户随意篡改历史记录而设置的。
  • 更清晰的历史记录。增加正确答案和做题数、错题数。使历史记录更加全面
  • 美观美化。增加了PictureBox控件,对齐了文本框和按钮。对于所有的控件固定了位置。

▶ 代码说明

  • 下图展示了出题部分的代码。将用户输入的信息传入接口以获得题目和答案,再将所有的题目答案保存到元组中,初始化做题信息。
 QuestionGenerator generator = new QuestionGenerator(//获取用户输入的参数
 	num_range_low: int.Parse(textBox1.Text.Trim()),
    num_range_high: int.Parse(textBox5.Text.Trim()),
    use_fraction: double.Parse(textBox11.Text.Trim()),
    MaxNodeCeiling: int.Parse(textBox12.Text.Trim()),
    symbol_set: arr, symbol_print: symbol_print);
try
{
    generator.Generate(int.Parse(textBox2.Text.Trim()));//生成题目和答案
}
catch (TimeoutException)
{
    MessageBox.Show("生成题目超时!该设置下无法生成足够数量的题目组合,请更改输入重试");
    return;
}                 
    Cnt = 0;
    var QA_pairs = generator.Get_QA_pairs();//得到题目和答案
    Q = QA_pairs.Item1;//题目放入元祖
    A = QA_pairs.Item2;//答案放入元祖
    textBox3.Text = Q[Cnt];//出的题目 
 //初始化
    right = 0;
    wrong = 0;
//做题:进度条
   progressBar1.Maximum = a_c;//设置最大长度值
   progressBar1.Value = 0;//设置当前值
   progressBar1.Step = 1;
//做题:开始计时
   timer1.Interval = 1000;//设置时间间隔为1秒(1000毫秒),覆盖构造函数设置的间隔
   currentCount = 21;
   timer1.Enabled = true;
   chutienabled = false;//不再允许点击出题按钮
   historyenabled = false;//不再允许点击历史记录按钮
  • 下图展示了做题功能的部分代码,只有在计时的过程中才算做题的过程。一旦不再计时,说明此事不能对输入文本框进行做题时的操作了。在按下会车时比对输入答案和正确答案,如果正确则通过,如果错误,则系统发出BEE——声,记录错题。然后重新出题,重新计时,进度条加一。
			if (timer1.Enabled)
            {
                if (e.KeyCode == Keys.Enter && textBox4.Text != "")//做题:每当按下回车时 // MYSRIO: 我觉得你想说text4(原来写的text3)
                {
                    if (Standardizer.Standardize_Number(textBox4.Text) == A[Cnt])   //直接与输入的值进行比较
                    {
                        right++;
                    }
                    else
                    {
                        Console.Beep();
                        //历史记录中....
                        a[history.Item1.Count] = A[Cnt];
                        history.Item1.Add(Q[Cnt]);
                        history.Item2.Add(textBox4.Text);
	                    wrong++;
                    }
                        Cnt++;
                    if (Cnt != int.Parse(textBox2.Text))
                    {
                        textBox3.Text = Q[Cnt];//出的题目 
                        currentCount = 21;//重新计时 
                    }
                    progressBar1.Value += 1;//进度条加一  
                    textBox4.Text = ""; //清空文本框
                    if (progressBar1.Value == int.Parse(textBox2.Text))
                    {
                        MessageBox.Show("恭喜完成所有题目!请点击提交按钮查看成绩结算!");
                        textBox3.Text = "";//每次答完题后清空
                        timer1.Enabled = false;
                        chutienabled = true;
                        
                    }
                }
                else if (e.KeyCode == Keys.Enter && textBox4.Text == "") 
                {
                    MessageBox.Show("请输入答案!");
                }
            }
            else
            {
                MessageBox.Show("此时不要调戏输入答案的文本框!");
            }
  • 下图展示了倒计时功能的部分代码,如果时间用尽且没有答题,则按照错题的方式处理。只有当题目全部做完并点击提交后,才能出题。
			if (currentCount > 0)
                currentCount -= 1;
            this.label2.Text = currentCount.ToString().Trim();
            if (currentCount == 0)
            {
                timer1.Enabled = false;
                MessageBox.Show("时间用尽!");               
                Console.Beep();
                //历史记录中....
                a[history.Item1.Count] = A[Cnt];
                history.Item1.Add(Q[Cnt]);
                history.Item2.Add(textBox4.Text);
	            wrong++;
                Cnt++;
                textBox4.Text = "";  
                if (Cnt != int.Parse(textBox2.Text))
                {
                    textBox3.Text = Q[Cnt];//出的题目 
                    currentCount = 21;//重新计时 
                    timer1.Enabled = true;
                }
                progressBar1.Value += 1;//进度条加一  
                if (progressBar1.Value == int.Parse(textBox2.Text))
                {
                    MessageBox.Show("题目已全部完成,请点击提交!");
                    chutienabled = true;
                }
            }
  • 下图展示了历史记录文件创建的过程,所属内容为按下提交按钮后。
 		string subPath = history_path;//history_path = "./ascii_history.txt"
           if (false == System.IO.File.Exists(subPath))//如果不存在文件
           {
               FileStream fs1 = new FileStream(history_path, FileMode.Create, FileAccess.ReadWrite);//则创建文件
               fs1.Close();
           }
           bug++;//控制只能打开多次但只写一次
           if (Flag==1)
           {
               if(Cnt==int.Parse(textBox2.Text))//提交功能
               {
                   timer1.Enabled = false;
                   Form2 score = new Form2();//展示结算
                   score.ShowDialog();
                   historyenabled = true;//允许点击历史记录
               }
               else
               {
                   MessageBox.Show("禁止提前交卷!");
               }
           }
           else
           {
               MessageBox.Show("尚未做题!");
           }
  • 下图展示了记录历史记录的功能。写的操作只有一次,且记录时间,错题详细信息(做错的题目、做错的答案、正确答案、做题数、错误数、正确率)。可以查看多次。
 			int n = Form1.wrong;
            textBox1.Text = Form1.Cnt.ToString();//总做题数
            textBox2.Text = Form1.right.ToString();//做对数
            textBox3.Text = (Convert.ToDouble(Form1.right) / Form1.Cnt).ToString();//正确率
            string path = history_path;
            if (Form1.bug == 1)//控制多次读一次写
            {
                for (int j = Form1.history.Item1.Count - 1; j > Form1.history.Item1.Count - n - 1; j--)//本次做题的错题
                {
                    string str1 = System.DateTime.Now.ToString() + " 题目:" + Form1.history.Item1[j].ToString() + " 错误答案:" + Form1.history.Item2[j].ToString()+"正确答案" + Form1.a[j]+"\n";
                    if (j == Form1.history.Item1.Count - n)//最后一道错题后
                    {
                        str1 += "共做:" + Form1.Cnt.ToString() + "题做错:" + Form1.wrong.ToString() + "题";
                        str1 += "正确率:";
                        str1 += (Convert.ToDouble(Form1.right) / Form1.Cnt).ToString();
                        str1 += "\n";
                    }
                    FileStream fs = new FileStream(path, FileMode.Append);//文本加入不覆盖
                    StreamWriter sw = new StreamWriter(fs, Encoding.Unicode);//转码
                    sw.WriteLine(str1);
                    //清空缓冲区
                    sw.Flush();
                    //关闭流
                    sw.Close();
                    fs.Close();
                }
            }

四、个人总结

非常感谢能够跟我的队友一起合作完成这个四则运算的软件,正是我们之间相互配合,相互理解,相互学习,才能这么为完美的完成老师交给我们的任务。在开发阶段刚开始不久,我得了病毒性感冒,4天都发着高烧不能下床。是队友的帮助和自己坚强的信念,让我带病坚持完成自己的任务。这次完整的开发过程,让我也意识到了自己的不足之处。首先是思考太局限的问题,很多的错误处理在一开始没有考虑全面,以至于到后面调试改错的时间占的特别的多。其次是对于新语言的学习能力还有待提高,尤其是对思维的转换,和一次性就记住的能力或记笔记的能力有待提高,来回的查找资料很浪费时间,因此系统的学习和多加练习很重要。最后我认识到前期的分析和设计对于软件开发来说十分重要,而且他们形成的文档对于后期排查错误,增加新功能或者改动来说是事倍功半的。这次的学习也激发了我对于小项目开发的兴趣,希望在日后自己能多动手,学习与制作其他形式的软件。加油ヾ(◍°∇°◍)ノ゙!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值