第二次结对编程作业
一、一些地址及分工
①队友博客链接
②本人博客链接
③Github项目地址
④具体分工
林青霞:UI
徐祖豪:AI
二、 PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟 |
Planning | 计划 | 30 | 40 |
· Estimate | · 估计这个任务需要多少时间 | 1800 | 2000 |
Development | 开发 | 1200 | 1400 |
· Analysis | · 需求分析 (包括学习新技术) | 60 | 60 |
· Design Spec | · 生成设计文档 | 30 | 20 |
· Design Review | · 设计复审 | 20 | 30 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 0 | |
· Design | · 具体设计 | 600 | 800 |
· Coding | · 具体编码 | 0 | |
· Code Review | · 代码复审 | 0 | |
· Test | · 测试(自我测试,修改代码,提交修改) | 120 | 140 |
Reporting | 报告 | 40 | 60 |
· Test Repor | · 测试报告 | 20 | 40 |
· Size Measurement | · 计算工作量 | 20 | 30 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 30 | 30 |
· 合计 | 2000 | 2650 |
三、 解题思路描述与设计实现说明
思路主要就是尽可能找到每一墩的最大的情况
-
接口使用
-
AI
算法的接口主要使用了永福提供的注册接口、登录验证接口、开启战局接口和出牌接口
注册:
import http.client
conn = http.client.HTTPSConnection("api.shisanshui.rtxux.xyz")
payload = "{\"username\":\"username\",\"password\":\"password\"}"
headers = { 'content-type': "application/json" }
conn.request("POST", "/auth/register", payload, headers)
res = conn.getresponse()
data = res.read() //拿到服务器的回应
登录:
conn.request("POST", "/auth/login", payload, headers)
res = conn.getresponse()
data = res.read()//拿到服务器的回应
//data里的token和user_id都是后面开启战局需要的
开启战局:
headers = { 'x-auth-token': "token" }
conn.request("POST", "/game/open", headers=headers)
res = conn.getresponse()
data = res.read()
使用token可以从服务器拿到一组牌,之后就是运行算法得出结果,再将结果发回服务器
payload = result
headers = {
'content-type': "application/json",
'x-auth-token': token
}
conn.request("POST", "/game/submit", payload, headers)
res = conn.getresponse()
data = res.read()
-
UI
注册:
javascript
url: "![img](file:///C:\Users\ADMINI~1\AppData\Local\Temp\%W@GJ$ACOF(TYDYECOKVDYB.png)https://api.shisanshui.rtxux.xyz/auth/register",
method: "POST",
header: {
'Content-Type': 'application/json'
},
data: JSON.stringify({
"username": this.data.username,
"password": this.data.password
}),
登陆:
javascript
url: "![img](file:///C:\Users\ADMINI~1\AppData\Local\Temp\%W@GJ$ACOF(TYDYECOKVDYB.png)https://api.shisanshui.rtxux.xyz/auth/login",
method: "POST",
header: {
'Content-Type': 'application/json'
},
data: JSON.stringify({
"username": this.data.username,
"password": this.data.password
}),
开始游戏:
javascript
url: "https://api.shisanshui.rtxux.xyz/game/open",
method: "POST",
header: {
'X-Auth-Token': app.globalData.token
},
排行榜;
javascript
url: "https://api.shisanshui.rtxux.xyz/rank",
method: "GET",
-
代码组织与内部实现设计
-
部分流程图
四、关键代码解释
cnt,all,rcd三个数组是此次算法的基础
在找到中墩或者底墩之后,记录剩余牌的数组将会发生变化,为了防止同一张牌出现两次影响后面的判断,所以被一次都要更新cnt、all和rcd三个数组
num_rcd=list(set(num_rcd).difference(set(down))) #更新num_rcd
#更新num_all
i=0
while i<5:
x = down[i]
num_all[x] = 0
i+=1
#更新num_cnt
i=0
while i<5:
x = int(down[i]/4)
num_cnt[x]-=1
i+=1
break
五、 性能分析与改进
①改进思路
性能分析发现搜索是最花时间的,所以在需要搜索的环节进行改进。
先进行数据处理,调用cnt、all和rcd数组分别记录,然后用Allstyle[7]依次往下记录各牌型,然后找后、中、前三个墩,用check_all()进行搜索,从Allstyle[7]往下搜索。
在前、中、后三个墩的搜索过程中,check_all()函数的执行最为耗时,所以想到在check函数里面引用函数,取代直接写。
一开始是想都用cnt+all的双重判断,会在两个数组内多次循环,造成不必要的支出。所以在判断顺子或者同花时,这两种牌型可以只用cnt判断是否存在五个符合的元素,如果存在则继续搜索,不存在则直接返回。
而对于对子、三条和炸弹这种只需要看数量的牌型则只需要循环找到cnt=n的那张牌。
②性能分析图
六、 单元测试
check_all()函数的功能是将剩下的牌中的所有的可能都保存起来
函数构造:
测试结果:
七、 Github的代码签入记录
八、困难及解决办法
- 问题描述
问题1、怎么描述一张牌
问题2、list 列表的append和+=用法不同导致结果列表里面会含有子列表 - 做过哪些尝试
问题1、一开始是想用类的方法描述,后面发现python没有结构体这个数据结构,自己构建又太麻烦,随意就把2-A的牌按花色不同排序,赋予0-51的值,使用NUM_ALL数组记录模拟牌
问题2、当判断可能存在一种牌型时,会使用列表来保存这个可能,如果这个可能的牌大于一张,且是使用append方法加入列表的,这个牌型可能就会存在小的列表,列表中的子列表是不能被迭代,这样在迭代时就会报错。后面改用+= 添加列表中的元素,问题解决。 - 是否解决
问题1、解决
问题2、解决 - 有何收获
加深了对于python语言的list数据结构的认识,而且本次作业大部分时间都在改bug,对于代码的异常调试也有了一些经验
九、 评价你的队友
林青霞:
- 值得学习的地方 😄
他很认真也很负责也很好道,代码编程能力很好,这很值得我学习。我就纯粹地被带。 - 需要改进的地方 😄
没什么能够挑剔的地方,但是就是线上交流居多,沟通不是特别流畅。
徐祖豪:
- 值得学习的地方 😄
做作业很积极,态度很认真,对于项目出现的问题在交流之后很快就能得到回应且想出解决方法。 - 需要改进的地方 😄
多学习新技术
十、 学习进度条
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
1 | 0 | 0 | 20 | 20 | 熟悉Axure RP用法 |
2 | 95 | 95 | 5 | 25 | 对牌进行分类 |
3 | 101 | 296 | 5 | 30 | 判断牌型 |
4 | 273 | 569 | 20 | 55 | 出牌策略、调试、改bug |