1. 地址
2. 分工
童景霖:完成AI的实现
黄永福:完成UI的实现
3. PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
· Planning | · 计划 | 30 | 20 |
· Estimate | · 估计这个任务需要多少时间 | 20 | 20 |
· Development | · 开发 | 240 | 300 |
· Analysis | · 需求分析 (包括学习新技术) | 200 | 600 |
· Design Spec | · 生成设计文档 | 30 | 30 |
· Design Review | · 设计复审 | 20 | 20 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
· Design | · 具体设计 | 60 | 80 |
· Coding | · 具体编码 | 200 | 240 |
· Code Review | · 代码复审 | 30 | 30 |
· Test | · 测试(自我测试,修改代码,提交修改) | 30 | 40 |
· Reporting | · 报告 | 40 | 60 |
· Test Repor | · 测试报告 | 20 | 15 |
· Size Measurement | · 计算工作量 | 20 | 25 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 20 |
· 合计 | 970 | 1510 |
4. 解题思路描述与设计实现说明
网络接口的使用
- 采用API文档中“注册与绑定”里的代码样例实现注册和绑定,其他功能也基本类似,将函数中的参数进行修改即可
- 将API返回的数据格式转换,利用json.load()转换成字典对象,再对字典进行处理获得所需要的数据
代码组织与内部实现设计(类图)
关键部分流程图
5. 关键代码解释
代码的关键部分
- AI_Part:
def find_card(c_list):
s1 = 0
s0 = 0
for x0 in itertools.combinations(c_list, 5):
list1 = c_list.copy()
x0 = list(x0)
a = gets_core(x0, 5)
if a < 20 :
continue
for y0 in x0:
list1.remove(y0)
for x1 in itertools.combinations(list1, 5):
list2 = list1.copy()
x1 = list(x1)
for y1 in x1:
list2.remove(y1)
x2 = list2
b = gets_core(x1,5)
c = gets_core(x2,3)
if (a >= b) and (b >= c):
s1 = a + 1.5*b + 2*c
if s1 > s0:
s0 = s1
global card
card.clear()
# 3 x2
str2 = get_str(x2,3)
# 5 x1
str1 = get_str(x1,5)
# 5 x0
str0 = get_str(x0,5)
card.append(str2)
card.append(str1)
card.append(str0)
-
利用itertools迭代器的combinations函数从13张牌中抽取5张作为后墩,判断后墩牌型,若为散牌则直接跳过;再从剩下的8张牌中抽取5张做为中墩,判断中墩牌型,若比后墩大,则直接跳过,重新搜索中墩;剩下的3张牌为前墩。
将各种牌型赋予一定的分数值,将前中后墩的牌型分数相加得到总分,总分最高的牌即为最终牌型,并返回。 -
UI_Part:
class IndexDetail(QtWidgets.QDialog, history_detail.Ui_Dialog):
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.setupUi(self)
self.res = API.history(MainWindow.TokenMine, IndexHistory.pid)
print(self.res['status'])
if self.res['status'] == 0:
self.res = self.res['data']
self.res = self.res['detail']
self.label_name.setText(str(self.res[0]['name']))
self.label_score.setText(str(self.res[0]['score']))
self.label_card.setText(str(self.res[0]['card']))
self.label_name_2.setText(str(self.res[1]['name']))
self.label_score_2.setText(str(self.res[1]['score']))
self.label_card_2.setText(str(self.res[1]['card']))
self.label_name_3.setText(str(self.res[2]['name']))
self.label_score_3.setText(str(self.res[2]['score']))
self.label_card_3.setText(str(self.res[2]['card']))
self.label_name_4.setText(str(self.res[3]['name']))
self.label_score_4.setText(str(self.res[3]['score']))
self.label_card_4.setText(str(self.res[3]['card']))
else:
self.label_card.setText('status:'+str(self.res['status']))
def back(self):
self.close()
w = IndexHistory(window)
w.show()
- 战局列表界面利用接口函数获取该局PID记录为类成员,在详情界面使用战局列表类成员PID来调用接口获取详情,并显示在GUI上,(如遇对局未完成等情况,显示返回的Status)
6. 性能分析与改进
性能分析图
程序中消耗最大的函数
改进思路
- 程序中消耗最大的函数是利用itertools迭代器,使用组合数列出13张牌能组成的所有牌型,再通过对每种情况的牌型进行评分,将分数最高的牌型输出。从13张牌中抽取5张,再从剩下的8张拍中抽取5张,最后剩下3张牌,这样组成牌的前、中、后墩。由于十三张牌能组成的牌型过多导致花费的时间很长。
- 由于每个人有13张牌,所以后墩必定不可能是散排(如果是散排则为一条龙),因此可以对后墩前进行判断,如果是散牌则可以直接跳过,考虑下一种情况;同样的也可以对中墩进行判断,如果中墩大于后墩,则跳过这种情况,但此时应保持后墩不变,改变中墩。其他的改进思路暂时还没想到。
7. 单元测试
def getnum(a):
return a.num
def tonghuashu(dun_b):
lista = []
listb = []
listc = []
listd = []
#分类
for s in dun_b:
if s.color == "#":
lista.append(s)
elif s.color == "$":
listb.append(s)
elif s.color == "&":
listc.append(s)
elif s.color == "*":
listd.append(s)
#排序
lista.sort(key=getnum)
listb.sort(key=getnum)
listc.sort(key=getnum)
listd.sort(key=getnum)
if len(lista) == 5:
liste = lista
elif len(listb) == 5:
liste = listb
elif len(listc) == 5:
liste = listc
elif len(listd) == 5:
liste = listd
else:
liste = []
l = len(liste)
i = 1
if l == 5:
flag = True
while i < l:
if liste[i].num != liste[i-1].num+1:
flag = False
break
i = i+1
else:
flag =False
if flag is True:
return liste[0].num
else:
return 0
a = tonghuashu(list)
print(a)
- 这是测试传入的中墩或者后墩是否为同花顺的代码
- 传入的牌事先经过处理以类的形式存放于列表s中,先将他们根据不同的花色进行分类,若某一种花色的数量达到5,再将其按牌的大小进行排序,检查是否是连续的牌型,是则为同花顺。
8. GitHub代码签入记录
9. 遇到的代码模块异常或结对困难及解决方法
问题描述
- AI_Part:
- 不会使用api
- 不懂得如何制作UI界面
- 数据类型直接的转换老是弄乱,对于一些函数的返回值类型不熟悉
- 使用迭代器模块时一直出现错乱
- UI_Part:
- QTDesigner网上教程资源过少(多为C++教程或者代码实现教程)
- .ui->.py 需要借助Pyuic工具,而我下的最新版的anaconda找不到Pyuic.exe的路径
- 右键.ui文件使用Pyuic进行.ui->.py时 点错成主模块即我的UI.py造成了整个UI.py代码丢失
- 调用显示继承来的窗口发生跳出
做过的尝试
- AI_Part:
- 百度查找相关资料以及到视频网站查找相应的教学视频
- 询问同学
- 不断测试,增加了很多测试点寻找问题
- UI.Part:
- 百度精确检索Pyqt5该关键词项
- 寻找原生的python文件里带该工具
- 发现有历史记录这个工具
英语水平过低未及时发现,经大佬提醒 - 发现继承来的窗口未定义自定义槽函数,一经调用,立马跳出!
是否解决
- AI_Part:
- 是
- UI_Part:
- 是
收获
- AI_Part:
- 对API的使用更加熟练了
- 能更加熟练的使用python,对python的了解也更多了
- 学习使用了python的itertools模块和time模块
- 简单掌握了pyqt5的使用,能用pyqt5做出一些简单的程序界面
- UI_Part:
- 熟悉API的使用,并能够根据所给的接口写模块
- 对python自带的工具栏更加熟悉
- 对python附加工具更加熟悉
- 对Pyqt5及QtDesigner熟练应用,并初步认识使用QtCreator
- 对GUI的Init有一定了解
10. 评价队友
值得学习的地方
- 有耐心
- 学习能力强
需要改进的地方
- 效率有待提高
11. 学习进度条
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
6 | 0 | 0 | 8 | 8 | 学习并能简单使用墨刀、ps等软件 |
7 | 800 | 800 | 12 | 20 | 学习python |
8 | 1200 | 2000 | 12 | 32 | 学习python和pyqt5 |