结对编程——四则运算器(UI第十组)
博客目录: 一、问题描述
二、设计思路
三、UI开发过程
四、对接过程
五、整体总结
六、对课程的两点建议
一、问题描述
本次结对编程作业分为以下两种类型Core(计算核心)和UI(用户界面),Core组负责根据设置要求生成一定数量的四则运算题目,UI组负责制作用户界面,然后两组对接完成一个完整的四则运算软件。具体要求详见:作业要求
二、设计思路
我们抽到的是UI组,负责界面的编写,我们选用的是Qt Creator这款编辑器。界面主要分为欢迎页(可在该页通过对话框设置参数)、答题页、反馈页(包括历史记录和错题汇总)。各个界面文字部分用label来写,倒计时用LCD number结合定时器来实现,用lineedit来接收用户的输入,页面之间使用信号和槽进行连接从而实现通过按钮来跳转,反馈页面中使用textedit向用户呈现结果。
三、UI开发过程
1.制作欢迎页以及设置对话框(4.5下午 驾驶员:胡宇晨, 领航员:张学忠)

工作重点在于使用label说明内容,pushbutton实现相应功能,使用对话框实现对参数的设置;
遇到的bug:设置对话框无法显示标题的所有内容,后发现对话框大小与提示说明的内容长度有关,后通过调节空格解决。
2.制作答题页面(4.5晚上 驾驶员:张学忠,领航员:胡宇晨)

工作重点在于使用lcdnumber显示器结合定时器实现倒计时功能,以及lineedit获取用户输入,通过确定按钮更新题目。
遇到的bug:
(1) 我们最初的想法是通过stackedwidget来实现切换页面从而更新题目,但是这样需要我们具体编辑一页的ui界面,当题目数量达到一定规模时这种方法就不再适用,解决方法是只设置一个页面,然后通过更新标签内容实现题目的跳转;
(2)当每更新到下一题时,上一题的答案仍然保留在文本框里,用户需要删除它之后再输入新答案,我们通过在每一次获取答案后将文本框置空的方法(代码为 ui->answer1->setText("");)解决了这个问题;
(3)上述(2)问题解决后,我们发现题目更新后光标并不在文本框中,于是我们加了一行代码 ui->answer1->setFocus(); 解决了这个问题。
3. 实现页面之间的跳转(4.6下午 驾驶员:胡宇晨,领航员:张学忠)
主要是通过信号和槽一一对应的方法来实现按钮触发页面跳转的:(下图实现从welcome页面通过按钮跳转到答题页面wodget)

之前我们试过在button的触发响应函数里使用accept(),然后通过检测accept信号实现跳转,但是这样的话代码需要编写在main()里面而且需要判断语句,后来我们通过查资料获知上述方法,用很清晰的结构实现页面跳转。之后的反馈阶段,我们在上述基础上还增加了页面回退的功能(主要是通过父子页面之间的带参传递)。
4. 数据处理及文件操作(4.6下午及晚上 驾驶员:张学忠,领航员:胡宇晨)
我们假定现已获取两个分别存放题目和答案的txt文件(produce_q和produce_a,每一行存放一道题或者一个答案并根据行号对应起来),我们的设计思路是在答题页面呈现之前从上述两个文件里分别逐行读取题目和答案,并存放到两个QString数组里(设为ques和ans),然后我们每次更新题目页面时就从ques数组里读出题目并显示在lineedit里,用户每答完一题我们就获取用户输入并与标准答案比对以统计得分(在用户答完最后一题时我们将告知用户其得分情况),同时把题目和用户输入作为一个完整的表达式写入文件history.txt,如果此题用户回答错误我们再将它写入文件error.txt并注释正确答案。整个过程我们全部使用文件的读写操作,其一是因为Qt的文件操作非常便捷,其二也是为了让用户在答题之后能获得一个存放记录的文件(不仅仅是通过我们的软件来查看)。
(这一阶段出奇地顺利,基本没有遇到什么bug)
5. 制作反馈页面、历史记录页面以及错题汇总页面(4.6晚上及4.7下午 驾驶员:胡宇晨,领航员:张学忠)

我们在上述数据处理和文件操作的基础上编写了历史记录和错题汇总界面,二者都可以通过反馈界面的相应按钮点击进入。
工作重点在于返回功能的设置,我们采用的是带参传递的方式:

(关于反馈页三个按钮功能的描述) (历史记录页面的返回功能,错题汇总页面同理)
遇到的bug:
(1)返回之后再进入历史记录页面无法打开history.txt,解决方法:在返回之前关闭文件history.txt(close函数);
(2) 如果在历史记录界面连续两次点击“查看”按钮会导致文件打开失败,解决方法:点击一次“查看”按钮后立即将其锁定(代码: ui->pushButton_2->setEnabled(false); ),从图中也可以看出。
6.重构设置界面(4.7晚上 驾驶员:张学忠,领航员:胡宇晨)
之前我们的设置界面是通过输入对话框InputDialog来实现的,这样的缺点在于每个设置的单项都会弹出一次,所以即使用户想选择默认值,仍然需要经历一遍所有的设置单项,而且不支持选择式的设置框,综合以上考虑我们准备仿照上面的历史记录和错题汇总界面。设计出来是下面这样的:(图片较大因为我们对之前的界面进行了放大处理)

设置项包括题目数量、题中操作数的最大取值、题中操作数的数量、操作数的数据类型、操作数的精度(如果是小数的话)以及支持的运算种类,设置框则采用了填空、单选和多选的形式,用户输入设置信息之后点击确定我们就获取这些信息传入Core组的设置输入接口,即可按照用户的需求进行题型的设置,如果用户放弃输入我们将使用默认值(上图的提示信息中已给出),如果用户输入不合法的值我们也会将其改为默认值。相应模块的代码如下:

(获取各设置项的值) (对不合法数据的处理)
至此整个UI界面部分就全部设计完成了,优化部分准备完成对接之后再行考虑。
四、对接过程
由于我们做的是与用户交互的UI界面,核心功能还是由core组完成的,需要对接之后才能完成四则运算器的具体功能。由于时间限制,我们目前只成功对接了五组core,先在此总结一下,之后对接工作还将继续。
1、吴雪晴组
对接采用动态链接库.dll,在debug模式下运用显式调用,成功地调用了dll中的函数,通过文件传递生成的题目和答案。界面和之前一样就不放图了,我们直接进txt看看吧!
假设我们设置题目数为10、操作数最大为100、操作数个数最大为10、操作数为整数、支持加减乘除和乘方:

(生成的十道题) (对应的答案)
对接过程中遇到的bug:
Qt调用dll:我们之前查资料得知隐式调用是最便捷的调用方法,但是调用之后程序一直报错(一直显示未定义),之后经查阅相关知识得知是因为MinGW编译器无法使用隐式调用,面对安装vs编译器和换用显式调用两种解决方法,我们选择了后者;在显示调用的过程中,我们发现函数在运行的过程中会报错而终止,后发现是可以连接上dll但连不上函数,查阅资料后得知是vs编译器在编译过程中会改变函数名,我们使用depends软件打开dll文件找到被改变的函数名,最后成功连上了函数。
2.刘梓轩组
同样使用显示调用动态链接库的方式,因有了和第一组对接的经验,此次对接较为顺利,但还是出了一些小bug:
(1)在他们提供的.h文件里,__declspec(dllexport)前为单短线,这在VS下可执行,但是在qt下会报错,手动改成了双短线;
(2)测试过程发现他们还有一小部分core的功能没有实现,经core组修改后解决了这个问题。
3.林静雯组
采用显示调用dll方式,对接过程也比较顺利,但检测出一个逻辑上的bug:
我们给调用的函数传递设置信息时,在运算类型这块出了一个bug,我们的思路是在ui界面上放置5个复选框分别对应加减乘除和乘方,如果我们检测到五个选项无一选中就将其默认为加减乘除,我们是使用一个标志flag_1完成这一步的,我们犯的错误是把赋默认值这一步放在了设置页面的按钮事件中,这样做的问题在于假如用户不进入设置页面直接开始答题的话,我们传入的这五个参数都将是0(初始值),这会导致dll崩溃(恰好对面的dll中没有这一步检测..)。这是一个低级的逻辑错误,我们把它写在这里是想给自己一个提醒。
4.耿子钢组
同样采用显示调用的方法,这一组的不同之处在于他们是使用结构体传参的,而之前几组都是用函数传的。我们遇到bug是关于参数传递的问题,我们和core组联系以后对方非常积极地帮我们调试,后来发现是因为他们对题目结果大小做了限制(1000以内),参数入口限制为:若只选择加减法,操作数允许在500以内,若选择了乘除,操作数则只允许在20以内。沟通之后我们对设置页面以及参数纠偏部分做了修改便对接成功了。
5.王亚正组
该组对接情况与第三组基本相同,在此不再赘述。
五、整体总结
1.结对编程的意义:
(1)互相监督,避免编程中的很多不必要的错误;
(2)针对每个模块,有更多的思路和方法,疏漏之处能及时发现,开发出的软件功能上也更加完善;
(3)遇到bug时,可以从更多的思维角度去解决,同时可以寻求更多的资源,使得问题的解决明显更加快捷;
(4)结对过程中,可以在遇到困难时相互鼓励,坚持沟通,保持良好的情绪,有助于项目的进展。
2.从结对编程中学到了什么?
(1)学习了Qt开发技能,了解了dll、lib等基本概念和使用方法,并初步接触到了MVC架构;
(2)对于编程过程中的一些逻辑规则、编码规范有了更深入的认识并加以实践;
(3)更加意识到了合作的重要性以及一些合作中的注意事项;
(4)从对接过程中认识到了沟通交流对于合作的重要性;
(5)解决问题的能力得到了很大的提升。
3.走上工作岗位后,是否选择结对编程用于解决部分任务?
我选择使用结对编程,因为结对编程可以大大提高项目开发的效率,尤其是工作量较大的项目,具体的原因上述两点已经详述,在此略过。
4.今后的团队作业,每周的任务,准备如何吸收个人作业、结对作业,改善开发流程?
团队作业也需要像结对作业一样,事先给出完整的架构,接口双方、前后端应当事先进行交流并制定出双方都同意的方案,避免后续的修改;团队作业中,对于部分模块也可以使用结对编程的模式以提高局部开发的效率;团队作业中,各个成员需要及时进行单元测试,排除bug,避免对团队造成影响。
六、对课程的两点建议
(1)减少课后作业量,课堂内容增加实用技能教学、减少理论知识介绍;
(2)希望作业要求更加明确,发布作业时能一锤定音;
PSP表格
| 步骤 | 预估耗时(小时) | 实际耗时(小时) |
| 计划 | 0.5 | 0.5 |
| ·估计开发时间 | 0.5 | 0.5 |
| 开发 | 83.4 | 95.6 |
| ·需求分析(包括学习新技术) | 8 | 10 |
| ·生成设计文档 | 0.5 | 0.5 |
| ·设计复审 | 0.5 | 0.1 |
| ·代码规范 | 0.5 | 0.3 |
| ·具体设计 | 1 | 2 |
| ·具体编码 | 12 | 16 |
| ·代码复审 | 0.5 | 0.5 |
| ·测试(包括对接过程) | 48 | 60 |
| 报告 | 6.2 | 8.1 |
| ·测试报告及博客 | 5 | 6 |
| ·计算工作量 | 0.2 | 0.1 |
| ·总结 | 1 | 2 |
| 合计 | 83.9 | 106.1 |
笔者能力有限,还请大家多多指教,感激不尽!!
参考博客:
结对编程——四则运算器(UI第十组)的更多相关文章
- 佛系结对编程---四则运算(Core 第四组)
----by core 第四组 ( 邹卫其 范力 ) 一. 项目介绍 1. 能自动生成小学四则运算题目并给出答案,生成题目时可以选择下列参数: 1)生成题目数量 2)每道题目中运算数数量 ...
- 现代软件工程HW2:结对编程-生成五则运算式-Core10组 [PB16110698+PB16120162]
作业具体要求点 这里 Core组要求: 1.Calc() 这个Calc 函数接受字符串的输入(字符串里就是算术表达式,例如 “5*3.5”,“7/8 - 3/8 ”,“3 + 90 * 0.3”等等) ...
- UI-12组结对编程作业总结
UI-12组结对编程作业总结 源码Github地址 https://github.com/tilmto/TILMTO/tree/master/Arithmetic 作业摘要 本次结对编程作业分为以下两 ...
- 高级四则运算器—结对项目反思(193 & 105)
高级四则运算器—结对项目反思(193 & 105) 本周我和一位韩国同学(71061105)一起结对编程完成了我们的结对项目——高级的小学四则运算题目生成器. PSP表格 PSP2.1 P ...
- 高级四则运算器—结对项目总结(193 &105)
高级四则运算器—结对项目总结 为了将感想与项目经验体会分割一下,特在此新开一篇博文. 界面设计 啥都不说,先上图震慑一下... 上面的三个界面是我们本次结对项目的主界面,恩,我也觉得挺漂亮的!你问我界 ...
- 结对编程项目总结(core2组)
结对编程项目总结(core2组) 作业---四则运算(Core 第二组) ----by 吴雪晴 PB16061514 齐天杨 PB16060706 一.项目简介 项目的任务为制作一个给(貌似是?) ...
- 结对编程收获——UI真的没有那么简单
结对编程收获——UI真的没有那么简单 詹元成 初看作业要求,心里还有一点欣喜,不就是做一个UI ...
- 结对编程-Core 第12组 [pb15061359+pb15061351]
一.项目要求 1.输入题目数量,生成操作数为3~5个的四则运算题目 2.输入上限值控制生成的操作数的最大值以及结果的最大值 3.输入支持的操作符类型:加.减.乘.除.乘方.括号 4.输入支持的操作数类 ...
- 结对编程UI
GitHub:https://github.com/zsl1996/UI/commits/master 一. 实验内容 这是交付给最终用户的软件,有一定的界面和必要的辅助功能.完 ...
随机推荐
- 监督学习——决策树理论与实践(上):分类决策树
1. 介绍 决策树是一种依托决策而建立起来的一种树.在机器学习中,决策树是一种预测模型,代表的是一种对象属性与对象值之间的一种映射关系,每一个节点代表某个对象/分类,树中的每一个分叉路 ...
- android开发 gradle 总结
gradle结构: MyApp ├── build.gradle ├── settings.gradle └── app └── build.gradle 1. setting.gradle解析 当你 ...
- mysql ERROR 1045 (28000): Access denied for user 可能解决方法分析
在实际登录redmine的过程中,我们遇到了如下的error ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using ...
- postman—集成到jenkins
前言 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 将postman导出的脚本,持续集成到 ...
- SQL中存储过程和函数的区别
转:https://www.cnblogs.com/jacketlin/p/7874009.html 本质上没区别.只是函数有如:只能返回一个变量的限制.而存储过程可以返回多个. 而函数是可以嵌入在s ...
- Joda-Time 学习笔记
一 Jode-Time 介绍 任何企业应用程序都需要处理时间问题.应用程序需要知道当前的时间点和下一个时间点,有时它们还必须计算这两个时间点之间的路径.使用 JDK 完成这项任务将非常痛苦和繁琐.既然 ...
- 安装和使用mongodb
环境: Ubuntu 13.04 安装MongoDB $sudo apt-get install mongodb 会自动安装libpcrecpp0 libboost-system1.42.0 libb ...
- rails 国际化、validate校验、flash提示
1.Rails的国际化 根据特定的locale信息,提取相应的内容 通过config/environment.rb,指定应用的转换文件 config.i18n.load_path +=Dir[Ra ...
- Java线程池,你了解多少?
一.前言 随着业务的发展,单线程已经远远不能满足,随即就有多线程的出现.多线程虽然能解决单线程解决不了的事情,但是它也会给你带来额外的问题.比如成千上万甚至上百万的线程时候,你系统就会出现响应延迟.卡 ...
- can/socket can
1. 概念 参考:Linux-CAN编程详解 can引脚: cn2: 15:CAN1_H 19 CAN1_L 根据每组报文开头的 11 位标识符(扩展帧为29位标识符.CAN 2.0A 规范)解释数据 ...