第二次结对编程作业
链接及地址
ui展示
具体分工
陈金杰负责对接及算法编写,蔡峰负责界面制作。
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 80 | 90 |
· Estimate | · 估计这个任务需要多少时间 | 80 | 90 |
Development | 开发 | 2930 | 3520 |
· Analysis | · 需求分析 (包括学习新技术) | 800 | 840 |
· Design Spec | · 生成设计文档 | 50 | 30 |
· Design Review | · 设计复审 | 100 | 80 |
· Coding Standard | · 代码规范 (为目前的开发制定或选择合适的规范) | 30 | 30 |
· Design | · 具体设计 | 900 | 930 |
· Coding | · 具体编码 | 960 | 1500 |
· Code Review | · 代码复审 | 40 | 30 |
· Test | · 测试(自我测试,修改代码,提交修改) | 50 | 80 |
Reporting | 报告 | 110 | 100 |
· Test Repor | · 测试报告 | 40 | 30 |
· Size Measurement | · 计算工作量 | 20 | 10 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出改进计划 | 50 | 60 |
· 合计 | 3120 | 3710 |
解题思路描述与设计实现说明
网络接口的使用
考虑到学习周期以及实际需求,选择了用web实现游戏的UI,用JS中的Ajax发送请求与服务器接口交互。以下为我们使用接口的几个实例:
点击查看
``` function login(){ var name=document.getElementById('username').value; var psw=document.getElementById('userpsw').value; var data={ "username":name, "password":psw } $.ajax({ url:'https://api.shisanshui.rtxux.xyz/auth/login', type:'POST', data:JSON.stringify(data), headers:{ "Content-Type":'application/json' }, success:function(data){ localStorage.setItem("token",data['data']['token']); localStorage.setItem("userid",data['data']['user_id']); window.location.href='game.html'; }, error:function(data){ alert("登录异常,请重试"); } }); } function query(){ var username=document.getElementById('queryUser').value; $.ajax({ url:'https://api.shisanshui.rtxux.xyz/history?player_id='+username+'&limit=3&page=1', type:'GET', dataType:'json', headers:{ 'X-Auth-Token':localStorage.getItem('token') }, success:function(data){ console.log(data); }, error:function(data){ alert('查询失败,请重试'); } }); } function logout(){ if (localStorage.getItem('token')!=null){ $.ajax({ url:'https://api.shisanshui.rtxux.xyz/auth/logout', type:'POST', headers:{ "Content-Type":'application/json', "X-Auth-Token":localStorage.getItem('token') }, dataType:'json', success:function(data){ localStorage.removeItem('token'); localStorage.removeItem('userid'); localStorage.removeItem('gameid'); localStorage.removeItem('card'); window.location.href='login.html'; }, error:function(data){ alert("注销失败,请重试"); } }); } } ```
代码组织与内部实现设计(类图)
建了一个类autoPlayer,大概逻辑是通过构造函数来接收手牌,初始化辅助数组,对每类牌型在每墩的情况下的价值就行评估赋值,并存在value矩阵中。然后通过自己设计的calculate函数贪心找出价值和最大的方案并返回
算法思路
* 对于这个问题的求解思路,大概分两步 * 第一步,较高效的枚举出所有的合法出牌方案 * 第二步,对于每个方案评估其价值 * 对于第一步,若靠朴素的全排列枚举搜索,是阶乘的复杂度,即13!。考虑到要面临的数据组数很多,这个复杂度并不好。我们可以发现其实全排列枚举,是会出现很多冗余计算的。因此考虑记忆化,我们可以预先枚举任意五张牌,记录下他们的可以构成的最大等级牌型,再预先枚举任意三张牌,做同样操作。 * 至于枚举和记录,也可以进行相应的小优化。以任选五张牌为例,我们假设对拿到的13张手牌按他们的位置下标进行编码,即0-12。再预先处理出二进制表示下1的个数为5的数(如31)的集合,我们只需枚举这个集合中的数,若当前数的第i位为1(二进制表示下),则表示选了第i张牌,显然这个集合里所有的数分别表示一种选5张牌的方案,从而实现了选牌方案映射到整型数的哈希。对处理任选三张牌也同理。 * 接下来就是通过我们预先记录的信息,枚举3,5,5的所有组合,过程中控制方案的合法性即可,选出认为价值最大的那种方案。 * 第一步的复杂度大概是O(2^13)的预处理+O(C(13,5)\*C(13,3))的枚举组合 * 对于第二步,就各自发挥想象力了,不多说。 * 综上,这种方法的时间复杂度是相当优秀的,但是效果如何就取决于第二步了。大致算法流程如下
关键代码解释
上述代码即预处理各种选3张、选5张方案下的最大牌型等级
上述代码通过一些简单的位运算来保证选牌方案的组合的合法性,同时也要保证三墩牌型等级的单调性,然后累加评估价值,尝试更新当前最优方案即可。
性能分析及改进
展示性能分析图和程序中消耗最大的函数
由上可知,用于初始化的构造函数和判断牌型的函数开销最大。
改进
考虑到该算法本身的时间复杂度较优秀,时间开销较小,再深入考虑效率优化,意义不大。 因此着重考虑算法的效果如何。通过百来盘的实战发现,该算法一开始的评估价值的方式过于粗糙,在相当一部分局面下,因小失大,没有顾及全局的最优。因此上网查阅资料,学习参考了前辈对于该游戏牌型的评估方法,重新细化了价值评估矩阵,从原来的两维抽象细分为三维矩阵,对于方案考虑其牌型、墩位、大小三个维度下的综合价值。 通过再次大量实战,发现效果果然明显改善。单元测试
跑了几组YF大佬服务器返回的数据,感觉效果挺ok。
贴出Github的代码签入记录
遇到的代码模块异常或结对困难及解决方法
蔡峰:
- 问题描述
首先当然是关于新技术的学习了。在上次作业里学习了axure9的基本用法后,这次需要学的就是制作网页界面的一些基础知识了。其次就是学习方法和新知识的运用了,学习新技术的方法一直被我认为是一个难点。最后就是这次结对情况到后期有一些匆忙,这完全是我在沟通交流上的的问题。 - 做过哪些尝试
一开始先是去到了w3school这个平台去学习,后来发现我的智商和接收能力实在是太弱了,于是在学习了一段时间后,我在学习的中后期来到了B站开启我的网课之旅,那还是比较嗨的。其次在学习方法和运用上,我向在这方面技术精通的学长取经,他给了我很多方向和指导意见,再加上队友的鼓励,辗转于向大佬问答和各种debug中。最后就是这次合作起来的确是有些匆忙,主要还是因为我的沟通问题和自身的知识储备太差了,以致于我们在时间上来不及、分工情况也受到了打击。 - 是否解决
问题都基本解决了,主要问题都能得到队友的理解和支持,并且他是一个real man,所以虽然我们这次十分匆忙,但各方面还是朝着好的方向去发展的。 - 有何收获
收获太多了,害,首先学到了许多知识吧,但其实这些知识运用起来有点繁琐和浪费时间,所以我感觉这次作业实在是有点累,主要是一波身体状况给我搞得有点自闭了。可能是胖了许多,身体在这段时间状况频发,所以还是给我造成了许多困扰。但是这恰好也是我的收获,在发烧的时候做网页是真滴嗨的一段经历(希望以后再也不要有了)。当然收获了和队友的友谊,第一次和大佬合作,这种感觉不一般。
陈金杰:
- 问题描述
之前只学过一点点后端,没有做过前端开发,这次要写能和后端交互的UI,有点无从下手。国庆节基本都在忙着训练,平常也要兼顾算法题练习,因此自由时间其实很少。 - 做过哪些尝试
无奈只能两倍速看JS网课速成,然后一边查资料,一边写。 - 是否解决
拿生命学习,那可不得解决了嘛 - 有何收获
很多事看起来很难做,实际上,它的确做起来也的确会很痛苦。
但一直做一直搞,好像也就成了。
这里查一查,那里问一问,动手试一试,扣扣空间骂一骂**软工课,好像也就熬过去了。。。(?)
评价你的队友
- 值得学习的地方
首先他真的很有责任心。他是一个很忙的人,有许多比赛要打,但是在一些我能力欠佳的方面他是真的能够提供巨大的帮助和支持,所以我觉得他为人还是十分nice。其次就是keep real,我在第一次博客就谈到过keep real是我的开山刀,当时和他组队也是因为几次看到他在大群里非常直接的几次谈吐,所以这是我最欣赏和佩服他的一点。最后就是他的能力,这个我想我不用做太多说明了,他是一个代码和学习能力十分优秀的人,执行力爆炸强。所以我觉得这也是我应该向他学习的地方。在日常听到许多人会抱怨自己的队友,但是如果再给我一次机会我还是会和他组队,再一百次也一样,但前提是他觉得ok。 - 需要改进的地方
金杰需要改进的地方,我想应该就是提前准备的习惯吧。我们这次的问题就是时间上有点赶,然后我不太了解他那里的进度,其他都莫问题的。
学习进度条
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
1 | 0 | 0 | 18.5 | 18.5 | 学会了原型设计工具Axure的基本使用方法,培养了一些审美(或许),学会了十三水的玩法 |
2 | 340 | 340 | 35 | 53.5 | 开始学习网页制作,并着手于算法设计 |
3 | 520 | 860 | 45 | 98.5 | 网页制作基本成型,开始交互工作;算法设计还差边角的修改 |
4 | 412 | 1272 | 40 | 138.5 | 基本完成ai和ui制作,工作收尾 |