2022软工K班结对编程任务
github:https://github.com/1daimon/main.git
bilibili:https://www.bilibili.com/video/BV1m8411W7wS/
小程序名称:北冥有鱼plus
一、结对探索(4分)
1.1 队伍基本信息(1分)
结对编号:13 ;队伍名称:煤油忒涩
学号 | 姓名 | 作业博客链接 | 具体分工 |
---|---|---|---|
032002109 | 陈艺栋 | 文本 | 程序主体,前端,后端,ai算法 |
032002107 | 陈曦 | 文本 | ui原型,ai算法、介绍视频 |
1.2 描述结对的过程(1分)
很明显,看学号,同一宿舍,好沟通,意见不同了,可以直接线下solo,反正人跑不掉。
1.3 非摆拍的两人在讨论设计或结对编程过程的照片(2分)
二、原型设计(16分)
2.1 原型工具的选择(2分)
我们选择了Pixso作为原型工具,这款工具的优势在于操作界面简单、功能丰富;内建资源多且免费;实时自动云存储且支持多人线上协作。打开文件速度快,操作丝滑,且入门难度不大,因而我们选择了它。
2.2 遇到的困难与解决办法(3分)
困难1:现成的素材库的素材如果直接用在原型中,会显得很违和,比如:一些按钮看起来不像按钮,反倒像花纹;
困难2:在进行背景图、主题图和logo设计时,能够找到的素材总是达不到我们的预想;
对困难1和困难2的解决方法:利用iPad的绘图软件Procreate对按钮图标、背景图、Logo、棋盘图等进行加工绘制,结合PS软件对相关图片进行处理调整,再运用至原型中,视觉效果有所改良。
困难3:设计Logo时,鲲鲲很难画好看,设计棋盘时,棋盘中间分界的小篆书很难写好看;
对困难3的解决方法:一点一点慢慢改,总会好看的。
2.3 原型作品链接(5分)
https://pixso.cn/app/share/f/Beznd0zwclsWpTjfUTnNXwKBHS-OdrWM
2.4 原型界面图片展示(6分)
整体预览
菜单页
注册页
登录页
个人主页
对战页
游戏规则页
我们的创新点
1.独具特色的LOGO
2.(重要!)后端采用unicloud 开发
三、编程实现(14分)
3.1 网络接口的使用(2分)
通过unicloud云开发进行后端接口的开发实现登录注册登出等等基础接口,使用java语言完成websocket的开发实现在线联机对战。
3.2 代码组织与内部实现设计(类图)(2分)
前后端
AI部分
3.3 说明算法的关键与关键实现部分流程图(2分)
前端部分逻辑
比较复杂的点关键在于,如何在对战对己方与对方的操作进行限制,防止错误操作导致游戏的混乱,即判断本方是否投掷骰子,本方是否下子,对方是否投掷骰子,对方是否下子。通过对一些变量的判断更改来进行提示与限制。
websocket
websocket实现的关键就是什么时候接收值什么时候传送值,如何实现客户端与服务器的互通。在进行在线对战时,先进入房间等待,服务器储存在房间等待的用户信息,随机分配对手,进入对战后,监听每个玩家的操作,并将落子结果与棋盘结果传送到服务器并由服务器将之转发给另一方。
AI部分逻辑
简单模式算法流程图如下:关键在于搜索未填格子最多的行
困难模式算法流程图如下:关键在于通过模拟计算得到下在每一格的预估收益,并且根据已填格子情况进行修改。
3.4 贴出重要的/有价值的代码片段并解释(2分)
前端
step_in1(index){if(this.please==0){this.dialogToggle1('info')return}if(this.click==1){this.dialogToggle3('info')return}if(this.use2==1){this.dialogToggle1('info')return}if(this.sum1[index]!=0){this.dialogToggle4('info')return}this.changenum1=1this.ready1=1this.click=1this.ready2=trueconsole.log(index)this.sum1[index]=this.result_numthis.ima_list1[index]=this.array_t[this.result_num-1]console.log((this.ima_list1[index]))this.ready=truethis.isShow= false// 更新domthis.$nextTick(()=>{this.isShow = true})this.use1=0this.click=1this.full=this.check(this.sum1)if(0<=index &&index<3){for (var i=0;i<3;i++){if(this.sum2[i]==this.sum1[index]){this.sum2[i]=0this.ima_list2[i]=''}}this.isShow= false// 更新domthis.$nextTick(()=>{this.isShow = true})}else if(3<=index &&index<6){for (var i=3;i<6;i++){if(this.sum2[i]==this.sum1[index]){this.sum2[i]=0this.ima_list2[i]=''}}this.isShow= false// 更新domthis.$nextTick(()=>{this.isShow = true})}else{for (var i=6;i<9;i++){if(this.sum2[i]==this.sum1[index]){this.sum2[i]=0this.ima_list2[i]=''}}this.isShow= false// 更新domthis.$nextTick(()=>{this.isShow = true})}if(this.full==1){console.log(this.sum1,this.sum2)this.score1=this.calculate(this.sum1)this.score2=this.calculate(this.sum2)if(this.score1>this.score2){this.winner='user1'}else{this.winner='user2'}this.message = `用户分数user1:${this.score1}user2:${this.score2}胜者:${this.winner}`this.dialogToggle5('info')return }},step_in2(index){if(this.please==0){this.dialogToggle1('info')return}if(this.click==1){this.dialogToggle3('info')return}if(this.use1==1){this.dialogToggle1('info')return} if(this.sum2[index]!=0){this.dialogToggle4('info')return}this.changenum2=1this.ready2=1this.click=1console.log(index)this.ready1=truethis.sum2[index]=this.result_numthis.ima_list2[index]=this.array_t[this.result_num-1]console.log((this.ima_list2[index]))this.isShow= false// 更新domthis.$nextTick(()=>{this.isShow = true})this.use2=0this.click=1this.full=this.check(this.sum2)if(0<=index &&index<3){for (var i=0;i<3;i++){if(this.sum1[i]==this.sum2[index]){this.sum1[i]=0this.ima_list1[i]=''}}this.isShow= false// 更新domthis.$nextTick(()=>{this.isShow = true})}else if(3<=index &&index<6){for (var i=3;i<6;i++){if(this.sum1[i]==this.sum2[index]){this.sum1[i]=0this.ima_list1[i]=''}}this.isShow= false// 更新domthis.$nextTick(()=>{this.isShow = true})}else{for (var i=6;i<9;i++){if(this.sum1[i]==this.sum2[index]){this.sum1[i]=0this.ima_list1[i]=''}}this.isShow= false// 更新domthis.$nextTick(()=>{this.isShow = true})}if(this.full==1){this.score1=this.calculate(this.sum1)this.score2=this.calculate(this.sum2)if(this.score1>this.score2){this.winner='user1'}else{this.winner='user2'}this.message = `用户分数: user1:${this.score1} ; user2:${this.score2} ; 胜者 ${this.winner}`this.dialogToggle5('info')return}},
这一部分是前端本地对战时,棋盘的点击事件函数,通过一些变量来控制操作的正确性,如判断是否已经摇过骰子,是否已经点击下子,是否下在本方棋盘,是否下载空格子,以及一些游戏规则的实现,如判断同行是否消去,游戏是否结束等。
后端
@OnOpenpublic void onOpen( Session session){this.session = session;index++;try {Result result = new Result();if(index%2==0){WebSocket socket1 = webSocketMap.get((index-1)+"");if(socket1!=null){result.setBout(true);result.setMessage("系统:游戏开始,请您先掷骰!");result.setColor("black");JSONObject json1 = JSONObject.fromObject(result);socket1.sendMessage(json1.toString());//对先掷骰的对象发送数据结束result.setMessage("系统:游戏开始,请等待对手掷骰!");result.setBout(false);result.setColor("white");this.sendMessage(JSONObject.fromObject(result).toString());//对后出手的发送消息结束}else{index--;result.setMessage("系统:等待玩家匹配!");this.sendMessage(JSONObject.fromObject(result).toString());}}else{result.setMessage("系统:等待玩家匹配!");this.sendMessage(JSONObject.fromObject(result).toString());}this.mykey = index;webSocketMap.put(mykey+"", this); //加入map中System.out.println(webSocketMap.size());} catch (Exception e) {e.printStackTrace();}}@OnMessagepublic void onMessage(String message) {System.out.println(message);JSONObject json = JSONObject.fromObject(message);Result result = (Result) JSONObject.toBean(json,Result.class);try {WebSocket socket = null;if(mykey%2==0){socket = webSocketMap.get((mykey-1)+"");}else{socket = webSocketMap.get((mykey+1)+"");}if(socket!=null){if(result.getXy()!=null&&!"".equals(result.getXy())){//有坐标表示为落子,反之则为发送信息this.sendMessage(message);result.setBout(true);//对手的bout改为true,表示接下来可以掷骰result.setMessage("系统:对方已掷骰,正在等待您掷骰!");socket.sendMessage(JSONObject.fromObject(result).toString());}else{Result newResult = new Result();newResult.setMessage("自己:"+result.getMessage());this.sendMessage(JSONObject.fromObject(newResult).toString());newResult.setMessage("对方:"+result.getMessage());socket.sendMessage(JSONObject.fromObject(newResult).toString());}}} catch (Exception e) {e.printStackTrace();}}
这一部分代码就是websocket其中的一段逻辑,其中就是判断房间内是否有人,对手是否匹配完成,对战是否开始。以及对于对方落子与棋盘的信息的转发。使用websocket主要是为了减少网络资源的损耗,而不必像http那样用轮询的方式来进行信息的接收与发送。
AI
int nextStep(int ownBoard[],int otherBoard[],int figure){float Block[3]={3,3,3};for(int i=0;i<9;i++){//获取格子填充情况if(ownBoard[i]!=0){if(i>=0&&i<=2) Block[0]--;else if(i>=3&&i<=5) Block[1]--;else if(i>=6&&i<=8) Block[2]--;}}//int ownScore=Getscore(ownBoard);int otherScore=Getscore(otherBoard);//for(int i=0;i<9;i++) cout<<ownBoard[i]<<" ";float D_value[9]={0};//计算操作差值for(int i=0;i<9;i++){if(ownBoard[i]==0) {int own1[9];for(int ii=0;ii<9;ii++) {own1[ii]=ownBoard[ii];//cout<<own1[ii]<<" ";}//cout<<endl;//复制一个ownboardint other1[9];for(int ii=0;ii<9;ii++) {other1[ii]=otherBoard[ii];//复制一个otherboard//cout<<other1[ii]<<" ";}//cout<<endl;//对数组进行操作own1[i]=figure;if(i>=0&&i<=2){//同行消灭处理for(int j=0;j<=2;j++){if(other1[j]==figure) other1[j]=0;}}else if(i>=3&&i<=5){for(int j=3;j<=5;j++){if(other1[j]==figure) other1[j]=0;}}else if(i>=6&&i<=8){for(int j=6;j<=8;j++){if(other1[j]==figure) other1[j]=0;}}int D_ownscore=Getscore(own1)-Getscore(ownBoard);int D_otherscore=Getscore(otherBoard)-Getscore(other1);int Differ=D_otherscore+D_ownscore;//获取操作后的差值D_value[i]=Differ;}}//至此D_value的值已经初步形成for(int i=0;i<3;i++){//根据已知格子权重赋值if(Block[i]!=0)switch (i){case 0:for(int j=0;j<3;j++){if(D_value[j]!=0) {D_value[j]+=Block[0]*2.5;if(Block[0]==3) D_value[j];if(Block[0]==2) D_value[j]-=0;if(Block[0]==1) D_value[j]-=3;if(D_value[j]<0) D_value[j]=0.1;}}break;case 1:for(int j=3;j<6;j++){if(D_value[j]!=0) {D_value[j]+=Block[1]*2.5;if(Block[1]==3) D_value[j];if(Block[1]==2) D_value[j]-=0;if(Block[1]==1) D_value[j]-=3;if(D_value[j]<0) D_value[j]=0.1;}}break;case 2:for(int j=6;j<9;j++){if(D_value[j]!=0) {D_value[j]+=Block[2]*2.5;if(Block[2]==3) D_value[j];if(Block[2]==2) D_value[j]-=0;if(Block[2]==1) D_value[j]-=3;if(D_value[j]<0) D_value[j]=0.1;}}break;default:break;}}float max = 0;float Di_value[9]={0.0};int flag=0;for(int i=0;i<9;i++) {//cout<<D_value[i]<<" ";if(D_value[i]>max){max=D_value[i];flag=i;}}//cout<<endl;return flag;
}
本函数中,先用Block数组记录已填格子情况,然后复制用于操作的数组,一个一个计算预计收益存入D_value数组中,再根据已填格子情况对预计收益进行调整,最后寻找预计收益最大的位置输出。
3.5 性能分析与改进(2分)
分析:存在一些代码冗杂,一些页面渲染的体验效果不是特别好,个别函数运行效率较为不理想。
改进:将复用多次的代码进行封装,将函数逻辑精简并减少循环。
3.6 单元测试(2分)
前端
前端采用console.log进行测试
后端
后端采用postman进行接口测试
3.7 贴出GitHub的代码签入记录,合理记录commit信息(2分)
四、总结反思(11分)
4.1 本次任务的PSP表格(2分)
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 60 |
Estimate | 估计这个任务需要多少时间 | 5 | 5 |
Development | 开发 | 900 | 1560 |
Analysis | 需求分析 (包括学习新技术) | 600 | 680 |
Design Spec | 生成设计文档 | 60 | 120 |
Design Review | 设计复审 | 30 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 15 | 10 |
Design | 具体设计 | 180 | 180 |
Coding | 具体编码 | 30 | 30 |
Code Review | 代码复审 | 180 | 180 |
Test | 测试(自我测试,修改代码,提交修改) | 300 | 360 |
Reporting | 报告 | 120 | 120 |
Test Report | 测试报告 | 60 | 45 |
Size Measurement | 计算工作量 | 30 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 30 |
合计 | 2570 | 3430 |
4.2 学习进度条(每周追加)
陈艺栋
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
1 | 0 | 0 | 30 | 30 | 学习了一下AI理论,以及一点后端知识 |
2 | 3215 | 3215 | 31 | 61 | 学懂了websocket,可惜的是学废了AI,理论与实践有差距, 但是完成了大部分的前端逻辑以及渲染 |
3 | 4622 | 7837 | 30 | 91 | 学了一下unicloud,体验了一下云开发,用云开发解决了除了websocket外的所有后端接口,websocket用java的框架实现 |
陈曦
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
1 | 0 | 0 | 8 | 8 | 学会了原型软件pixso的用法,开始用Procreate、pixso、PS做UI设计 |
2 | 0 | 0 | 9 | 17 | 学习websocket,但没有投入实际使用,完成了原型设计 |
3 | 482 | 482 | 8 | 25 | 完成了三种难度模式的AI,完成了测试程序 |
4.3 最初想象中的产品形态、原型设计作品、软件开发成果三者的差距如何?
我们最初想象中的产品是界面简洁美观,带有一点中国古风的、满足账号登录登出、能够实现本地对战、人机对战、在线对战三大功能,其中人机对战适配有不同的难度的、带有在线排行榜单、个人成绩记录等功能的、人机交互友好,用户操作舒适的微信小程序。
原型设计作品做得差强人意,UI设计方面,由于原型设计者有些艺术细胞,但软件技术有待提高,小程序界面较为美观,但不够简约,在图标和按钮设计和原型交互设计上,原型设计者也遇到了各种问题,不得不将要求一再放低,在原型上没能实现模拟对战,是本次原型设计的一大遗憾(原型设计者真的很努力在做了QAQ)
最终开发出的软件是较为接近最初设定的产品形态的,除在线排行榜单功能,最初计划的功能均已实现。主要差距在用户体验不够尽善尽美,实际对战过程中,存在偶发的卡顿现象,是本软件的瑕疵。
4.4 评价你的队友
陈艺栋:我的队友陈曦值得学习的地方在于他的灵活运用能力比较强,能够想到各种方法、活用会用的工具应对遇到的问题,在美工设计上能够设计出符合一般审美的图形、图像,安排的任务也会尽心尽力去做;需要改进的地方在于他的工作和学习效率不够高,而且时间管理能力有待提高,经常出现时间安排不过来的情况,常导致作息不规律,精力不集中,这样效率就更不高了。
陈曦:我的队友陈艺栋给人一种很踏实的感觉,他学习能力强、编程能力强,在本次作业中完成了最为复杂、工作量和难度都非常大的前后端,让我有一种抱大腿的感觉;他值得学习的地方是优秀的时间管理能力和强大的自律性,这两点都是我欠缺的。需要改进的地方是为我安排任务时表达得不是很详细具体,稍稍有些缺少与我的沟通。
4.5 结对编程作业心得体会(3分)
-陈艺栋
作业难度:单说作业难度的话,最为困难的话对我而言是实现websocket和AI,因为之前没怎么碰过后端以及AI的训练.其它的总体而言难度还好.
完成后的感受:爽,很爽,非常爽,卸下了一个包袱,就是有些地方自己不是很满意.
代码模块异常:恶心我最久的就是websocket的实现,因为没碰过,要从0到1有点难度,还有就是unicloud的实现与流程也常报错.
结对困难与解决方法:困难就在于AI与后端,我俩都不太擅长.所以我俩就学,直接莽上去,撸起袖子加油熬夜.
启发:与队员的合作要经常交流,同时时间安排一定要合理,避免项目的拖延以及实现效果的不足.还有就是要有去碰壁去解决难题的勇气.困难在开发过程中一定是一个主旋律.
-陈曦
作业难度:对我来说这个作业是比较难的,因为我没有什么开发经验,很多东西都不懂,幸好有一个很好的队友.
完成后的感受:终于结束了,感觉自己又活过来了
代码模块异常:在我们训练学术ai失败后,选择用算法来模拟ai,这一块我的出错比较多,逻辑不够清晰.
结对困难与解决困难:困难就在于AI与后端,撸起袖子加油熬夜,可惜最后ai的训练训出了一个鬼东西,不如自己重写一个算法.
启发:学习要趁早,不要书到用时方恨少,就是自己的能力不足,导致此次项目完成的比较痛苦.
2022软工K班结对编程任务相关推荐
- 2022软工K班结对编程作业
逍遥骰GitHub链接 哔哩哔哩功能展示 学号 姓名 作业博客链接 具体分工 032002621 林灿彬 待填写 JavaScript编程.AI设计 032002623 林达锴 待填写 原型制作.ht ...
- 01组-2022软工K班现场编程任务
一.B站视频链接 哔哩哔哩 二.整体架构思维导图 三.任务分工与得分比例 姓名 任务 任务量占比 廖国均 项目统筹.发布任务 100% 林展 代码实现 120% 高浩楠 博客撰写 90% 程玉莹 代码 ...
- 2022软工K班第一次博客作业
2022软工K班第一次博客作业 一.自我介绍 二.思考 三.未来的期望 一.自我介绍 1.1 自我介绍 项目 内容 姓名 林毅 性别 男 昵称 云淡风轻/平安是福/上善若水 学号 012004114 ...
- 2022秋软工实践 第一次结对编程作业
2022秋软工实践 第一次结对编程作业 需求分析 (1)Need,需求 (2)Approach,做法 (3)Benfit,好处 (4)Competitors,竞争 (5)Delivery,推广 UML ...
- 2021秋软工实践第一次结对编程作业
这个作业属于哪个课程 构建之法-2021秋-福州大学软件工程 这个作业要求在哪里 2021秋软工实践第一次结对编程作业 这个作业的目标 实现博饼软件原型并进行博客写作 学号 031902139 队友学 ...
- 2022软件工程K班结对编程任务
https://github.com/vincigeorge/Pair_work2/tree/main https://www.bilibili.com/video/BV1Ee411L7zR/?vd_ ...
- 2021秋软工实践第一次结对编程作业-需求分析
博饼软件需求分析 一.简要说明 博饼,是厦门人几百年来独有的中秋传统活动,是一种独特的月饼文化,也是厦门人对历史的一种传承.现在,博饼依然是厦门人最钟爱的中秋活动,也是最热闹的一个民俗节日形式. 目前 ...
- 软工网络15结对编程练习(201521123007谭燕)
链接 学号:201521123006:博客链接: http://www.cnblogs.com/KimHeechul/p/8644402.html 学号:201521123007:博客链接: http ...
- 软工网络15结对编程练习
一.链接 结对编程成员博客园地址: 201521123009 徐璐琳 博客园地址:http://www.cnblogs.com/abonxxxu/ 码云地址:https://gitee.com/abo ...
- 软工网络15结对编程练习 201521123056 吴剑通
0.结对编程成员: 吴剑通博客地址:https://www.cnblogs.com/wjt960310/ 杨钧宇博客地址:http://www.cnblogs.com/GOB8023/ 码云地址:ht ...
最新文章
- 博士后工作站来了!智源研究院获得正式授牌
- C#+WebSocket+WebRTC多人语音视频系统
- php使用redis做缓存,php使用redis做缓存和使用redis保存session
- 使用tensoflow serving来部署模型推理节点
- jQuery修改页面元素的属性
- HUST 1353 Dartboard
- 002-一般处理程序(HttpHandler)
- 联想小新打印机M7268W配置步骤
- 阿里巴巴面试题- - -Java体系最新面试题(2022内部资料)
- android 圆形自定义进度条,自定义Android圆形进度条(附源码)
- Android 计算网络速度文件下载剩余时间<<最优方案>>
- Matlab p文件解密,p转m文件 可查看源码
- php 公众号授权登录,微信公众号授权登录
- 浏览器在线视频播放加速方法——直接修改网页代码实现加速
- Android打开日历账号管理,Android 日历CalendarProvider
- nssl 1438.战略威慑
- 怎样把WORD表格转换成EXCEL
- 36岁,被单位解聘,我干起了深夜外卖
- Mac如何安装numpy,pandas,matplotlib,spicy等包,以及下载速度慢遇到read timed out问题如何解决
- 新冠“照妖镜”,体质弱点现原形。你是啥症状?2023年,请好好善待你的身体!