第二次结对编程作业
目录
1. 文章开头给出链接(2分)
2. 具体分工(2分)
姓名 | 分工 |
---|---|
杨世杰 | 负责AI相关:设计出牌算法,提供AI部分博客内容。 |
张越洋 | 负责UI相关:设计交互界面,提供UI部分博客内容。 |
3. PSP表格(2分)
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 40 | 80 |
Estimate | 估计这个任务需要多少时间 | 30 | 35 |
Development | 开发 | 560 | 800 |
Analysis | 需求分析(包括学习新技术) | 240 | 300 |
Design Spec | 生成设计文档 | 60 | 40 |
Design Review | 设计复审 | 30 | 30 |
Coding Standard | 代码规范(为开发制定合适的规范) | 25 | 15 |
Design | 具体设计 | 80 | 120 |
Coding | 具体编码 | 500 | 1000 |
Code Review | 代码复审 | 60 | 90 |
Test | 测试(自我测试,修改,提交修改) | 30 | 90 |
Reporting | 报告 | 60 | 100 |
Test Report | 测试报告 | 20 | 30 |
Size Measurement | 计算工作量 | 10 | 20 |
Postmortem & Process Improvement Plan | 事后总结并提出过程改进计划 | 30 | 50 |
合计 | 1775 | 2800 |
4. 解题思路描述与设计实现说明(15分)
- 网络接口的使用(3分)
本次作业使用了python的requests库进行get和post的操作,把所有需要用的接口整合在api.py中,并归属于同一玩家类下,便于随时提取和使用token,user_id,cards等成员。
- 代码组织与内部实现设计(类图)(6分)
Play类下包含用户名密码等成员变量,同时包含各种接口函数,card下则主要包含找出三墩牌的方法,对手牌按花色排序,对手牌按大小排序的方法,normal下则主要包含找各种牌型的方法。具体如图
- 说明算法的关键与关键实现部分流程图(6分)
本次算法是基于贪心算法的改进:首先从单张到同花顺给予权值1~9,第一遍循环中寻找权值最大的牌型并得到后墩,第二遍循环则寻找权值等大或次大的牌型作为中墩,留下的最后三张牌则作为前墩。同时,找牌时还需同时考虑其他墩牌的的情况,表现在找炸弹剩下的单牌不能凑对子,葫芦的对子不能凑葫芦,大牌型配小单张等...具体实现如图:
5. 关键代码解释(3分)
-
贴出你认为重要的/有价值的代码片段,并解释(3分)
以找葫芦为例,首先找到最大的三张,其次找最小的对子,且该对子不能与其他牌凑成葫芦,否则找下一个对子:
def hulu(cards): # 传入按大小降序序的牌
s = cards[0:1]
for i in range(len(cards) - 1):
if flag(cards[i + 1]) == flag(cards[i]):
s.append(cards[i + 1])
if len(s) == 3:
break
else:
s = cards[i + 1:i + 2]
if len(s) != 3:
return 0
cards_dels = [card for card in cards if card not in set(s)][::-1] # 删去葫芦后剩下的牌并返回升序的牌
d = cards_dels[0:1] # 开始找最小对子
for i in range(len(cards_dels) - 1):
if flag(cards_dels[i + 1]) == flag(cards_dels[i]):
d.append(cards_dels[i + 1])
if len(d) == 2 and i != len(cards_dels) - 2 and flag(cards_dels[i + 1]) != flag(cards_dels[i + 2]) and flag(cards_dels[i - 1]) != flag(
cards_dels[i]): # 确保对子不会与其他牌凑成葫芦
break
else:
d = cards_dels[i + 1:i + 2] #若对子能和其他牌构成葫芦,则继续寻找下一个对子
else:
d = cards_dels[i + 1:i + 2]
if len(d) != 2:
return 0
else:
return s + d
6. 性能分析与改进(6分)
- 描述你改进的思路(5分)
- 起初采取的是贪心算法,即每一步都找权值最大的牌型(包括里面的单张)
- 在此基础上进行改进,从概率上考虑,将里面的小牌型(葫芦中的对子,炸弹中的单张)替换成权值更小些的牌
- 在此此基础上进行改进,由于后(中)墩的牌会影响中(前)墩(葫芦带的对子可以和剩下的牌凑成三条/葫芦,两对带的单张可以和剩下的牌凑成对子),于是对这些问题进行解决,得到最终Ver3.0
- 展示性能分析图和程序中消耗最大的函数(1分)
性能分析采用PyCharm的Profile分析工具,从服务器随机取了10组手牌,在本地离线运行(避免网络接口函数的影响),可以看到,调用和消耗最多的是flag()函数,因为涉及到牌大小的比较就会调用该函数,因此调用次数会较多。
7. 单元测试(5分)
-
展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路
给出几组ver2.0和ver3.0算出的结果会不同的数据(即同时考虑多墩的情况下找到的最优解)
cards = ['*2', '&2', '&3', '&6', '#2', '#3', '&K', '&7', '*6', '$2', '*Q', '#10', '*8'] print("cards:", cards) print("ans:", findAns(cards)) cards = ['*2', '#Q', '#3', '&4', '*3', '*J', '*9', '#2', '*K', '&7', '$3', '#7', '$2'] print("cards:", cards) print("ans:", findAns(cards)) cards = ['*3', '#2', '$2', '&J', '&5', '*7', '&K', '*5', '$6', '#3', '#6', '#7', '$7'] print("cards:", cards) print("ans:", findAns(cards))
测试结果:
8. 贴出Github的代码签入记录(1分)
-
请合理记录commit信息
9. 遇到的代码模块异常或结对困难及解决方法(8分)
- 杨世杰(后端)
问题描述(2分) | 做过哪些尝试(2分) | 是否解决(2分) | 有何收获(2分) |
---|---|---|---|
api接口不会使用 | 查找资料参考 | 是 | 学会了requests库使用和http请求方法 |
算出的结果不够好 | 查阅资料并想办法优化 | 是 | 对一些算法有进一步认识 |
- 张越洋(前端)
问题描述(2分) | 做过哪些尝试(2分) | 是否解决(2分) | 有何收获(2分) |
---|---|---|---|
pygame模块加载图片失败 | 更换图片路径、换IDE | 是。似乎默认路径是工作区文件夹根目录 | |
pygame模块的现成的类不够用,没有按钮、文本框、列表之类的 | 自己实现、向同学请教 | 是 | python的GUI模块确实不好用 |
10. 评价你的队友(4分)
- 评价人:杨世杰
值得学习的地方(2分)
尽责耐心,思路较清晰,经常忙到很晚。
需要改进的地方(2分)
(双方)时间观念需要加强,后面总是天天熬夜TAT
- 评价人:张越洋
值得学习的地方(2分)
认真:严肃对待课题,经常打代码到到半晚
需要改进的地方(2分)
代码能力(当然我更有必要加强代码能力)
11.学习进度条
- 杨世杰
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
1 | 100 | 100 | 10 | 10 | 学会了python基本语法和对list等数据类型的操作,学会了玩十三水 |
2 | 300 | 300 | 5 | 20 | 还是在学习python... |
3 | 1100 | 1400 | 23 | 40 | 学习了requests等模块的使用,对api有了更深程度的了解 |
- 张越洋
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 无 |
2 | 300 | 300 | 5 | 5 | 不应毫无规划就打代码 |
3 | 1100 | 1400 | 23 | 28 | 学习网络接口的使用、学习pygame模块的使用 |
值得推荐
pygame教程