第二次结对作业

1、各种地址

结对同学博客
本次作业博客
我所fork的同名仓库的github项目地址

2、给出具体分工

兴源做ai,我做ui和api调用。

3、psp表格

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

(1)网络接口的使用

思路就是把api生成的代码复制到代码上,然后有需要变量的地方(token,uid)在登陆时用正则表达式获取,有需要在ui显示出来的东西通过python自带的tkinter的label或button的text变量显示出来。
具体实现是通过python的request库来实现,下面是一个登陆的例子

        url = "https://api.shisanshui.rtxux.xyz/auth/login"
        headers = {
            'content-type': 'application/json'
        }
        data = {
            "username": username,
            "password": password
        }
        dataa=str(data)
        response = requests.request("POST", url, data=dataa, headers=headers)
(2)代码组织与内部实现设计(类图)

这部分是兴源实现的,文本来自兴源的博客:

(3)说明算法的关键与关键实现部分流程图

这部分是兴源实现的,文本来自兴源的博客:

  • 算法的关键是进行组合和筛选
  • 关键实现部分流程图

5、关键代码解释

这部分是兴源实现的,文本来自兴源的博客:

import itertools
def cmb(list0):
    list1 = list0.copy()
    iter1 = itertools.combinations(list1, 5)
    while 1:
        try:
            tup0 = next(iter1)
            listc = list(tup0)
            list1 = list0.copy()
            for i in range(5):
                list1.remove(listc[i])
            iter2 = itertools.combinations(list1, 5)
            while 1:
                try:
                    tup1 = next(iter2)
                    liste = list(tup1)
                    listf = list0.copy()
                    for i in range(5):
                        listf.remove(listc[i])
                    for i in range(5):
                        listf.remove(liste[i])
                    a = getscore(listc, 5)
                    b = getscore(liste, 5)
                    c = getscore(listf, 3)
                    if a > b and b > c:
                        listsum[1] = a + 2 * b + 3 * c
                        if listsum[1] > listsum[0]:
                            listsum[0] = listsum[1]
                            global lians
                            lians.clear()
                            for k in range(3):
                                lians.append(listf[k])
                            for k in range(5):
                                lians.append(liste[k])
                            for k in range(5):
                                lians.append(listc[k])
                except StopIteration:
                    break

        except StopIteration:
            return

这段代码采用组合数的方法,即先从13张牌中随机选出5张一堆,再从剩下的8张牌中选出5张一堆,剩下3张一堆。遍历c(13,5)c(8,5)c(3,3)种所有可能的情况,再用getscore函数进行判断,选出符合规则且得分最高的组合方式。

6、性能分析与改进

这部分是兴源实现的,文本来自兴源的博客:

  • 在刚开始设计AI的实现方法时,我想过使用递归的贪心算法:(1)底墩先贪心的选能够组合最大的牌型的5张牌,再递归调用自身从剩下的8张中选贪心5张最大牌型,最后剩三张。(2)然后底墩贪心选能够组合次大的牌型的5张牌,再递归调用自身从剩下的8张中选贪心5张最大牌型,最后剩三张。(3)底墩再选第三大...以此类推,直到底端是对子。(4)剩余8张选5张也类似,贪心选最大,然后次大,直到散牌。(5)最终用getscore函数给每堆打分,判断出三墩牌是否符合规则,最终分数最高的三墩牌即是要求的牌。但是这种情况下选出的牌,牌型判断变得很复杂,存在较多不确定性,对写代码实现不友好,就放弃了这种思路,改用组合数遍历所有可能的方法。即每次从13张中随机挑5张,再从剩下8张中挑5张,最后三张一堆,然后每种组合都用getscore函数给每堆打分,判断出三墩牌是否符合规则,最终分数最高的三墩牌即是要求的牌。

  • 性能分析图

  • 其中消耗最大的函数是组合数遍历所有可能的comb()函数(在上面关键代码处已经展示过),而消耗第二大的getscore()函数与其相差不大,因此我就展示一下getscore()函数,这个函数是用于给每一墩牌打分的。

def getscore(li, m):
        listb = li.copy()
        f=0
        f = tonghuashun(listb)
        if f > 0:
            return 100 + f * 0.01
        f = zhadan(listb)
        if f > 0:
            return 90 + f * 0.01
        f = hulu(listb)
        if f > 0:
            return 80 + f * 0.01
        f = tonghua(listb, m)
        if f > 0:
            return 70 + f * 0.01
        f = shunzi(listb, m)
        if f > 0:
            return 60 + f * 0.01
        f = santiao(listb)
        if f > 0:
            return 50 + f * 0.01
        f = liandui(listb)
        if f > 0:
            return 40 + f * 0.01
        f = liangdui(listb)
        if f > 0:
            return 30 + f * 0.01
        f = duizi(listb, m)
        if f > 0:
            return 20 + f * 0.01
        else:
            dict1 = {}
            for x in range(2, 15):
                dict1[x] = 0
            for r in listb:
                dict1[r.num] = dict1[r.num] + 1
            f = 0.1
            t = 0
            for i in range(14,1,-1):
                if dict1[i]>0:
                    t =t+ i * f
                    f =f*0.1
            return 10+t

7、单元测试

import unittest
import shisanshui

class MyTestCase(unittest.TestCase):
    def test_santonghua(self):
        result = shisanshui.santonghua()
        self.assertEqual(result, 1)


if __name__ == '__main__':
    unittest.main()
  • 这是用来测试三同花的测试代码,
  • 测试数据的构造思路
    • 满足三同花,
    • 有两个同花
    • 有一个同花
    • 没有同花

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

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

问题描述:在点击开始游戏按钮后,因为整个程序在while(true)循环里面,然后窗口界面就停止工作了
做过哪些尝试:在while里面增加sleep,把按钮和文本的载入放到while里面,将while循环去掉
是否解决:是
有何收获:虽然还是不知道怎么才能让他一边自己出牌一边显示,但是我用最少的时间解决了这个问题,而且题目也没说ui的这个功能要怎么设计,所以越快做完就越好啦。

10、请评价你的队友

值得学习的地方:能够独立完成当初分配的任务,不用我操心ai的部分
需要改进的地方:能做完ai我已经很满足了,硬要说改进的地方就是不要在deadline当天才完成收尾工作,能提前一两天就好了。

11、学习进度条

12、ui演示视频

https://pan.baidu.com/s/1fjkJ007D2GbNprHNU8G9_w
由于注册界面会新弹窗出来,就另外截图

posted @ 2019-10-15 14:11  b6666666666666666b  阅读(213)  评论(3编辑  收藏  举报