1、链接
结对同学的博客地址:https://www.cnblogs.com/wy-1997/p/11751557.html
本作业博客地址:https://www.cnblogs.com/zyh233/p/11750810.html
GitHub项目地址:https://github.com/icey0012/shisanshui
2、分工
前端:曾宇辉
后端:王银
3、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(min) | 实际耗时(min) |
---|---|---|---|
Planning | 计划 | 50 | 40 |
Estimate | 估计这个任务需要多少时间 | 50 | 40 |
Development | 开发 | 1610 | 1920 |
Analysis | 需求分析 (包括学习新技术) | 600 | 750 |
Design Spec | 生成设计文档 | 60 | 50 |
Design Review | 设计复审 | 60 | 50 |
Coding Standard | 代码规范 (为开发制定合适的规范) | 30 | 30 |
Design | 具体设计 | 200 | 200 |
Coding | 具体编码 | 500 | 570 |
Code Review | 代码复审 | 80 | 70 |
Test | 测试 (自我测试,修改,提交修改) | 180 | 200 |
Reporting | 报告 | 135 | 150 |
Test Report | 测试报告 | 45 | 60 |
Size Measurement | 计算工作量 | 30 | 30 |
Postmortem & Process Improvement Plan | 事后总结 并提出过程改进计划 | 60 | 60 |
合计 | 1795 | 2110 |
4、解题思路描述与设计实现说明
4.1、 权值比对表
4.2、网络接口的使用
def opengame():
global token,id
url = "https://api.shisanshui.rtxux.xyz/game/open"
headers = {"X-Auth-Token": token}
response = requests.post(url, headers=headers)
message=response.json()
id=message["data"]["id"]
card=message["data"]["card"]
print(response.text)
return card
def login_check():
global token
url = "https://api.shisanshui.rtxux.xyz/auth/validate"
headers = {"X-Auth-Token": token}
response = requests.get(url,headers=headers)
print(response.text)
4.3、代码组织与内部实现设计(类图)
5、关键代码解释
def dfs_1(d, index_1): #/ * 枚举组合 * /
for i in range(d,13+1):
s1[i] = 1#标记,防止重复拿取
temp_1[index_1] = poker_1[i]#挑选
if index_1 == r1 :#r1=5,挑选够5张进入下一个dfs_2()函数,架构与dfs_1一样
init_1()#初始化dfs_2()函数,清空等操作
dfs_2(1, 1)
else:
dfs_1(i + 1, index_1 + 1)
s1[i] = 0
统计花色与牌号:
统计牌型用桶排序,dict用于统计花色和牌号,list用于储存牌组结构体
for i in range(1,3+1):
hua[ans_3[i].flower] +=1
number[ans_3[i].num]+=1
权值判断与细化:
以前墩部分牌型为例,总细化权值=细化权值 x 细化级别
for i in range(1,4+1):
if hua[i] == 3:
if shunzi3(ans_3[1].num) == 1:
k=(9.0+0.9 / 11.0 * (ans_3[1].num - 1))
score += k
return k # 3张同花顺
for i in range(3,0,-1):
if number[ans_3[i].num] == 1:
x = ans_3[i].num
if number[ans_3[i].num] == 2:
k=(1.0 + 0.9/(130+13)*((ans_3[i].num - 1)*10+x-1)*1.0)
score += k
return k#单对
k=0.9 / (1300.0 + 130.0 + 13.0)*((ans_3[3].num - 1) * 100 + (ans_3[2].num - 1) * 10 + (ans_3[1].num - 1))
score += k
return k #散牌
6、性能分析与改进
改进的思路
一开始的时候由于用python写速度会比较慢一些,运行时间到了10几秒
经过性能分析,发现在每次抓组合数时候的桶排dict_init()还有constrast()判断函数消耗了很大一部分的时间,于是进行了优化,
最后成功让算法的性能有所提高,达到了5-6秒钟作业。
性能分析图和程序中消耗最大的函数
性能分析图如下所示消耗最大的函数是Second,就是计算中墩的函数。
改进后,发现在判断连对和炸弹等嵌套情况可以暂时储存数据,
同时按牌数循环,将原有的O(n3)复杂度降到了O(n2),大大减少了中墩和后墩消耗的时间
最后进行了搜索剪枝优化,将原有的一次耗时8-9秒降低80%,完成了1秒内出答案
7、单元测试
单元测试这部分我们测试主要对三个函数进行测试,其他函数因为功能十分简单,所以就没有进行测试。测试的三个函数分别是得到前墩、中墩、后墩的三个函数,由于结构基本一样,只有变量的改变,所以只给出一部分的代码。各测试数据都是在手机app“大头十三水”读出的数据,然后为了提高一些代码的覆盖,我们尽可能的挑选了不同的数据进行测试,尽可能的覆盖更多的代码分支。而且由于前墩中墩后墩的结果会互相影响,即前墩挑出后要先把前墩的牌剔除再放入中墩函数进行计算,所以中墩的测试数据是在手动剔除前墩的基础上得到的,后墩同理。最后得出的结果与我们设计的算法的思路是一致的。
覆盖率:
class MyTestCase(unittest.TestCase):
def testfirst(self):
weig0 = 10
weig1 = 7
weig2 = 6
self.assertEqual(shisanshui.first(str0), weig0)
self.assertEqual(shisanshui.first(str1), weig1)
self.assertEqual(shisanshui.first(str2), weig2)
def testsecond(self):
weig0 = 10
weig1 = 9
weig2 = 8
self.assertEqual(shisanshui.second(str0), weig0)
self.assertEqual(shisanshui.second(str1), weig1)
self.assertEqual(shisanshui.second(str2), weig2)
def testthird(self):
weig0 = 10
weig1 = 9
weig2 = 8
self.assertEqual(shisanshui.second(str0), weig0)
self.assertEqual(shisanshui.second(str1), weig1)
self.assertEqual(shisanshui.second(str2), weig2)
8、Github的代码签入记录
9、遇到的代码模块异常或结对困难及解决方法
-
问题描述
前端这一部分的编写。
结对沟通的问题。
除了算法其实都有问题,之前没有做过一个稍微完整的项目,所以很多东西都没有学过,也没有这方面的知识。
python性能太慢,每一次抓取循环需要8-9秒 -
做过哪些尝试
因为刚开始讨论的时候算法前端都用python来写,后来听到有人说什么python写出来的前端会有问题,导致进度一度拖着……,实在没办法只能硬着头皮上,还要学习pygame、pyqt…学的东西真的多。对没有学习的东西,只能靠搜索引擎和B站了。
对搜索算法进行了剪枝,优化80%以上,只需要1秒便能得到答案 -
是否解决
都已解决了 -
有何收获
感受就是速成太难了,计算机的世界太复杂。需要学的东西太多了。。。。要到处找资源找教程。
10、评价你的队友
值得学习的地方:
责任心强,对于作业细心严谨
需要改进的地方:
对于作业过程中的难题还需要共同进步
11、学习进度条
第N周 | 新增代码(行) | 累计代(行) | 本周学习耗时(小时) |
---|---|---|---|
1 | 300 | 300 | 10 |
2 | 600 | 900 | 10 |
3 | 600 | 1500 | 15 |