第二次结对编程作业

强颜欢笑 提交于 2019-12-01 10:25:16

1、队友链接

2、分工

  • 我负责UI的编写以及在前端加入api接口与界面交互相连接
  • 出牌算法大部分由大哥完成,我负责了其中特殊牌型的判断

3、PSP表格

PSP2.1 Personal Software
Process Stages
预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 40
· Estimate · 估计这个任务
需要多少时间
10 20
Development 开发 960 1250
· Analysis · 需求分析
(包括学习新技术)
120 240
· Design Spec · 生成设计文档 30 40
· Design Review · 设计复审 30 20
· Coding Standard · 代码规范
(为目前的开发
制定合适的规范)
30 30
· Design · 具体设计 60 40
· Coding · 具体编码 480 360
· Code Review · 代码复审 30 40
· Test · 测试(自我测试,
修改代码,提交修改)
180 480
Reporting 报告 170 270
· Test Repor · 测试报告 90 120
· Size Measurement · 计算工作量 20 30
· Postmortem & Process
  Improvement Plan
· 事后总结,
并提出过程改进计划
60 120
  合计 1160 1560

4、解题思路描述与设计实现说明

思路描述

  • 首先,数据规模为$n=13$很容易想到枚举算法(大概是$O(13^{5} * 8^{5}$)?貌似也没有限时),只要暴力枚举前中墩的情况即可,因 - 为前中墩枚举结束后,剩余牌自动归为前墩。
  • 其次,对于枚举结束之后的三墩,先进行合法性检测,即三墩需满足:前墩$\lt$中墩$\lt$后墩等号取不到
  • 再者,对于合法的一组手牌,我们算出这组牌赢的概率的估计值。对,是概率的估计值,那么如何计算?因为我们偷到了一个权重数组,同时,我们维护一个大小为25的大根堆队友说25吉利,显然最后堆顶的牌组就是我们考虑的最优组合。
  • 最后,发到服务器,等待出分。

设计实现说明

  • 爆搜或者10重for的嵌套。简单粗暴,除了久一点,没什么问题。
  • 爆搜或者5重for,先选出后墩,再选出中墩。即后中墩是分开选择的。显然可以出解,而且比上一种方法快很多。但是,会出现倒水的情况,即无法保证三墩的大小关系。
  • AI算法,笔者没有头绪。
  • 最后选择了方法1因为一开始写的是方法2,发现倒水了,就被队友说服去写方法1了

类图




流程图

5、关键代码解释

#从api请求返回的排行榜数据
# 将json格式转换成单元格内容
item = [(j, c, data[c].values()) for j in range(3) for c in range(len(data))]
for v in item:
    #print('行下标%s,列下标%s,值:%s' % (v[1], v[0], list(v[2])[v[0]]))
    newitem = QTableWidgetItem(str(list(v[2])[v[0]]))
    newitem.setTextAlignment(Qt.AlignHCenter | Qt.AlignBottom)
    if v[0]==1 or v[0]==0:
        self.tableWidget.setItem(v[1], v[0]+1, newitem)  
    else:
        self.tableWidget.setItem(v[1], v[0]-2, newitem)

6、性能分析与改进

    ncalls  tottime  percall  cumtime  percall
       64    0.001    0.000   15.890    0.248 Algorithm_fight.py:142(get_battle)
       32    0.030    0.001    8.021    0.251 Algorithm_fight.py:155(decode_data)
       32    0.001    0.000    3.058    0.096 Algorithm_fight.py:168(my_choose)
      800    0.000    0.000    0.000    0.000 Algorithm_fight.py:180(<lambda>)
       32    0.001    0.000    7.483    0.234 Algorithm_fight.py:204(send_2_system)
       32    0.055    0.002   26.529    0.829 Algorithm_fight.py:221(_start)
        1    0.000    0.000   26.530   26.530 Algorithm_fight.py:239(main)
      416    0.000    0.000    0.000    0.000 Algorithm_fight.py:29(chg)
        1    0.000    0.000    0.000    0.000 Algorithm_fight.py:37(Hands)
    50944    0.019    0.000    0.025    0.000 Algorithm_fight.py:38(__init__)
   292872    0.034    0.000    0.034    0.000 Algorithm_fight.py:42(__lt__)
       32    0.125    0.004    3.056    0.096 Algorithm_fight.py:49(RecommendHands)
        1    0.000    0.000   26.767   26.767 Algorithm_fight.py:7(<module>)
        1    0.000    0.000    0.000    0.000 GetWeight.py:7(<module>)
    50944    0.240    0.000    2.790    0.000 GetWeight.py:99(get_weight)

参数解释:

  • ncalls:表示函数调用的次数。
  • tottime:表示指定函数的总的运行时间,除掉函数中调用子函数的运行时间。
  • percall:(第一个 percall)等于 tottime/ncalls。
  • cumtime:表示该函数及其所有子函数的调用运行的时间,即函数开始调用到返回的时间。
  • percall:(第二个 percall)即函数运行一次的平均时间,等于 cumtime/ncalls。
  • filename:lineno(function):每个函数调用的具体信息
  • 其实,撇开网络请求,自我感觉完成得还是不错的。

7、单元测试

class UnitTest(unittest.TestCase):
    
    @classmethod
    def setUpClass(self):
        pass

    @classmethod
    def tearDownClass(self):
        pass

    def tst_jdg_pair(self):
        ct = 0
        for i in open('./UnitTest-in.txt').readlines():
            ct += 1
            nw = []; cards = i.split()
            for j in cards:
                nw.append((suit_sa[j[0]],number_sa[j[1:len(j)]]))
            #print(nw)
            print("card %d " % (ct), end="")
            print(jdg_pair(nw))

    def tst_jdg_2pairs(self):
        ct = 0
        for i in open('./UnitTest-in.txt').readlines():
            nw = []; cards = i.split()
            for j in cards:
                nw.append((suit_sa[j[0]],number_sa[j[1:len(j)]]))
            #print(nw)
            ct += 1
            print("card %d " % (ct), end="")
            print(jdg_2pairs(nw))

    def tst_jdg_triple(self):
        ct = 0
        for i in open('./UnitTest-in.txt').readlines():
            nw = []; cards = i.split()
            for j in cards:
                nw.append((suit_sa[j[0]],number_sa[j[1:len(j)]]))
            #print(nw)
            ct += 1
            print("card %d " % (ct), end="")
            print(jdg_triple(nw))

    def tst_jdg_boom(self):
        ct = 0
        for i in open('./UnitTest-in.txt').readlines():
            nw = []; cards = i.split()
            for j in cards:
                nw.append((suit_sa[j[0]],number_sa[j[1:len(j)]]))
            #print(nw)
            ct += 1
            print("card %d " % (ct), end="")
            print(jdg_boom(nw))

    def tst_jdg_straight(self):
        ct = 0
        for i in open('./UnitTest-in.txt').readlines():
            nw = []; cards = i.split()
            for j in cards:
                nw.append((suit_sa[j[0]],number_sa[j[1:len(j)]]))
            #print(nw)
            ct += 1
            print("card %d " % (ct), end="")
            print(jdg_boom(nw))

    def tst_jdg_flush(self):
        ct = 0
        for i in open('./UnitTest-in.txt').readlines():
            nw = []; cards = i.split()
            for j in cards:
                nw.append((suit_sa[j[0]],number_sa[j[1:len(j)]]))
            #print(nw)
            ct += 1
            print("card %d " % (ct), end="")
            print(jdg_flush(nw))

    def tst_jdg_fullhouse(self):
        ct = 0
        for i in open('./UnitTest-in.txt').readlines():
            nw = []; cards = i.split()
            for j in cards:
                nw.append((suit_sa[j[0]],number_sa[j[1:len(j)]]))
            #print(nw)
            ct += 1
            print("card %d " % (ct), end="")
            print(jdg_fullhouse(nw))

test_lists = ["tst_jdg_pair","tst_jdg_2pairs","tst_jdg_triple","tst_jdg_boom","tst_jdg_straight","tst_jdg_flush","tst_jdg_fullhouse"]
if __name__ == "__main__":
    for i in test_lists:
        suit = unittest.TestSuite()
        suit.addTest(UnitTest(i))
        runner = unittest.TextTestRunner()
        runner.run(suit)

8、贴出Github的代码签入记录


9、遇到的代码模块异常或结对困难及解决方法

问题描述

曾世缘:

  • 结对没有尽早开始写代码,拖延得比较后面。国庆当然是快乐
  • 关于算法结果有冲突。倒水我是不想重写的

庄锡荣:

  • PyDesinger每个页面制作完成后,在页面的切换出现问题,无法通过按钮相互切换
  • Mainwindow弹窗功能使用不了

做过哪些尝试

曾世缘:

  • 意识到快来不及了,马上动工233
  • 队友说得对,就重写吧。

庄锡荣:

  • 查阅别人实现的代码,阅读Pyqt5接口文档
  • 根据别人的用法基础上修改,找到能使自己的Mainwindow可以弹窗的用法

是否解决

曾世缘:

+较好解决。显然我们完成了作业,我也解决了倒水。

庄锡荣:

  • 解决且实现了弹窗问题和窗口页面相互切换调用

有何收获

曾世缘:

  • 队友是个好队友,我就不知道了。
  • 学了一下python自带堆heapq的使用

庄锡荣:

  • 依旧是觉得做前端很累
  • 学习新语言的使用还是要多尝试,在实践中不断踩坑,在踩坑中不断成长

10、评价你的队友

值得学习的地方

  • 儒雅随和,不紧不慢。
    需要改进的地方
  • 老是喊累,不想进取。

11、学习进度条

第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
1 0 0 10 10 学会markdown写博客
2 500 500 26 36 学会json格式使用
使用request库调用API
3 0 0 21 57 使用Axure进行原型设计
设计出征战十三水原型
4 600 1100 16 73 使用Pyqt进行UI设计
设计出征战十三水UI

心得:

曾世缘:

1、感谢我的队友,考虑到我的各种原因,包揽了前端,还写了特殊牌型得判断,最后放我来写我自己最熟悉的算法部分,同时队友也非常体谅我的进度。平心而论,如果这次是个人作业,我可能就完成不了了,或者说只会做出一个非常丑陋的UI界面。
2、一开始想写爆搜,怕爆栈就丢了for上去,确实除了慢点没什么问题,剪了剪枝也没有非常出乎意料的提升。暴力出奇迹,这是我写过最暴力的工程代码,但是却有着极低的编程复杂度。

庄锡荣:

1、这次的结对作业也算为之后的团队作业打下基础吧,自己应该学会如何去管理调整整个项目的进度,合理的发挥每个人的长处,而不是都堆积在一起实现一两个功能。
2、应该尽早开始做提前准备工作,而不是临时开始学习要用的东西,赶工出来的结果一定不会是最优秀的作品。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!