第二次结对编程作业

结对同学博客链接

本博客链接

github地址

UI视频地址

1. 具体分工

西西西瓜萌:UI设计、前端实现、初版算法的实现、博客撰写

雨霖铃0000:提供算法思路、改进算法的实现、算法分析测试、博客撰写

2. PSP表格

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

3. 解题思路与设计实现

  • 解题思路
    首先,通过接口进行注册登录获取token,战局开始后取得13张扑克,通过遍历的方式找出最大的牌型,并赋予其特定的分值,当牌型一样时,分值更大的那一种排法优先,赋牌顺序为后墩、中墩、前墩。

  • 网络接口的使用

    • 注册
      • AI
    url = "https://api.shisanshui.rtxux.xyz/auth/register"
    payload = "{\"username\":\"un\",\"password\":\"pw\"}"
    headers = {'content-type': 'application/json'}
    response = requests.request("POST", url, data=payload, headers=headers)
    print(response.text)
      • UI
    url: "https://api.shisanshui.rtxux.xyz/auth/register",
    method: "POST",
    header: {
        'Content-Type': 'application/json'
    },
    data: JSON.stringify({
        "username": this.data.username,
        "password": this.data.password
    }),

    • 登陆
      • AI
    url = "https://api.shisanshui.rtxux.xyz/auth/login"
    payload = "{\"username\":\"un\",\"password\":\"pw\"}"
    headers = {'content-type': 'application/json'}
    response = requests.request("POST", url, data=payload, headers=headers)
    print(response.text)
      • UI
    url: "https://api.shisanshui.rtxux.xyz/auth/login",
    method: "POST", 
    header: {
        'Content-Type': 'application/json'
    },
    data: JSON.stringify({
        "username": this.data.username,
        "password": this.data.password
    }),

    • 开启战局
      • AI
    url = "https://api.shisanshui.rtxux.xyz/game/open"
    headers = {'x-auth-token': tkk}
    response = requests.request("POST", url, headers=headers)
    print(response.text)
      • UI
    url: "https://api.shisanshui.rtxux.xyz/game/open",
    method: "POST",
    header: {
        'X-Auth-Token': app.globalData.token
    },

    • 出牌
      • AI
    url = "https://api.shisanshui.rtxux.xyz/game/submit"
    payload = "{\"id\":" + idd + ",\"card\":[\"" + qian +"\",\""+ zhong +"\",\""+ hou +"\"]}"
    print(payload)
    headers = {
        'content-type': "application/json",
        'x-auth-token': tkk
    }
    response = requests.request("POST", url, data=payload, headers=headers)
    print(response.text)
    • 历史战局详情
      • UI
    url: "https://api.shisanshui.rtxux.xyz/history",
    data: {
        "player_id": this.data.id,
        "limit": this.data.n1,
        "page": this.data.n2
    },
    method: "GET",
    header: {
        'content-type': 'application/json',
        'X-Auth-Token': app.globalData.token
    },

    • 历史战局列表
      • UI
    url: 'https://api.shisanshui.rtxux.xyz/history/'+this.data.id,
    data: {
        "id": this.data.id,
    },
    method: "GET",
    header: {
        'content-type': 'application/json',
        'X-Auth-Token': app.globalData.token
    },

    • 排行榜
      • UI
    url: "https://api.shisanshui.rtxux.xyz/rank",
    method: "GET",

  • 代码组织与内部实现设计(类图)

  • 说明算法的关键与关键实现部分流程图
    实现关键:按照牌型大小顺序来判断出牌

4. 关键代码解释

就拿取出后墩的函数third()来说

def third():
    global score
    init_cnt()
    bubble_sort(ans_1, 1, 5)
    x = 1
    for i in range(1, 6):
        hua[ans_1[i].flower] = hua[ans_1[i].flower] + 1
        number[ans_1[i].num] = number[ans_1[i].num] + 1
    x = 1
    for i in range(1, 6):
        if hua[i] == 5:
            if ShunZi5(ans_1[1].num) == 1:
                k = (9.0 + 0.9 / 9 * (ans_1[1].num - 1)) * 1.0  # 14 13 12 11 10
                score += k
                return k  # 同花顺
    x = 1
    for i in range(5, 0, -1):
        if number[ans_1[i].num] == 4:
            x = ans_1[i].num
        if number[ans_1[i].num] == 4:
            k = (8.0 + 0.9 / (130 + 13) * ((ans_1[i].num - 1) * 10)) * 1.0
            score += k
            return k  # 炸弹
    x = 1
    for i in range(5, 0, -1):
        if number[ans_1[i].num] == 3:
            x = ans_1[i].num
            for j in range(5, 0, -1):
                if number[ans_1[j].num] == 2:
                    k = (7.0 + 0.9 / (130 + 13) * ((x - 1) * 10 + ans_1[j].num - 1)) * 1.0
                    score += k
                    return k  # 葫芦
    x = 1
    for i in range(1, 6):
        if hua[i] == 5:
            k = (6.0 + 0.9 / (130000 + 13000 + 1300 + 130 + 13) * (
                        (ans_1[5].num - 1) * 10000 + (ans_1[4].num - 1) * 1000 + (ans_1[3].num - 1) * 100 + (
                            ans_1[2].num - 1) * 10 + (ans_1[1].num - 1))) * 1.0
            score += k
            return k  # 同花
    x = 1
    if ShunZi5(ans_1[1].num) == 1:
        k = (5.0 + 0.9 / 9 * (ans_1[1].num - 1) * 1.0)
        score += k
        return k  # 5张顺子
    x = 1
    for i in range(5, 0, -1):
        if number[ans_1[i].num] == 3:
            x = ans_1[i].num
            for j in range(5, 0, -1):
                if number[ans_1[j].num] == 1:
                    k = (4.0 + 0.9 / (1300 + 130 + 13) * ((x - 1) * 100))
                    score += k
                    return k  # 三条
    x = 1
    for i in range(5, 0, -1):
        if number[ans_1[i].num] == 2:
            for j in range(5, 0, -1):
                if (ans_1[i].num != ans_1[j].num) and \
                        number[ans_1[j].num] == 2 and abs(ans_1[i].num - ans_1[j].num) == 1:
                    k = (3.0 + 0.9 / 10 * (ans_1[j].num - 1 - 1)) * 1.0
                    score += k
                    return k  # 连对2对
    x = 1
    for i in range(5, 0, -1):
        if number[ans_1[i].num] == 2:
            for j in range(5, 0, -1):
                if (ans_1[i].num != ans_1[j].num) and number[ans_1[j].num] == 2:
                    k = (2.0 + 0.9 / (130 + 13) * ((ans_1[i].num - 1) * 10 + ans_1[j].num - 1)) * 1.0
                    score += k
                    return k  # 普通2对
    x = 1
    for i in range(5, 0, -1):
        if number[ans_1[i].num] == 1:
            x = ans_1[i].num
        if number[ans_1[i].num] == 2:
            k = (1.0 + 0.9 / (130 + 13) * ((ans_1[i].num - 1) * 10 + x - 1)) * 1.0
            score += k
            return k  # 单对+3张散

    k = (0.9 / (130000 + 13000 + 1300 + 130 + 13) * (
                (ans_1[5].num - 1) * 10000 + (ans_1[4].num - 1) * 1000 + (ans_1[3].num - 1) * 100 + (
                    ans_1[2].num - 1) * 10 + ans_1[1].num - 1)) * 1.0
    score += k
    return k

先将未使用过的牌进行排序,在排好的序列中循环依次判断有无同花顺、 炸弹 、葫芦、 同花、顺子、三条、二对连对、普通二对、一对、散牌的牌型,牌型从大到小为:同花顺 > 炸弹 > 葫芦 > 同花 > 顺子 > 三条 > 二对连对 > 普通二对 > 一对 > 散牌,k为此牌型得到的分值,牌的大小越大,k值越大,从而得到最优的后墩牌型。

5. 性能分析与改进

  • 展示性能分析图

  • 程序中消耗最大的函数

    由profile分析图可以看出消耗最大的函数是排序函数bubble_sort(),用于提取中墩和后墩的second()和third()中用到了冒泡排序函数,并且要在全局进行循环遍历,所以消耗也比较大。

  • 改进的思路
    将second()和third()两个函数中不必要的循环用if加以判断,减少排序消耗。

6. 单元测试

  • 使用python的unittest模块,构建专门的单元测试类,进行部分单元测试代码
import unittest
from 13water import Card
from 13water import bubble_sort
import 13water

class Testbubble(unittest.TestCase):
    def setUp(self):
        pass

    def tearDown(self):
        pass

    poker_1 = [Card(0, 0) for i in range(14)]

    poker_1[1] = Card(2, 2)
    poker_1[2] = Card(3, 2)
    poker_1[3] = Card(4, 2)
    poker_1[4] = Card(1, 3)
    poker_1[5] = Card(1, 4)
    poker_1[6] = Card(4, 5)
    poker_1[7] = Card(1, 6)
    poker_1[8] = Card(1, 7)
    poker_1[9] = Card(2, 9)
    poker_1[10] = Card(3, 8)
    poker_1[11] = Card(4, 4)
    poker_1[12] = Card(4, 8)
    poker_1[13] = Card(3, 5)

    bubble_sort(poker_1,1,14)

    for i in range(1,14):
        print(poker_1[i].num,end=" ")

if __name__ == "__main__":
    unittest.main()

  • 测试的函数
    排序函数bubble_sort()

  • 构造测试数据的思路
    给出13张可能遇到的牌,令bubble_sort()将其排序,只有排序正确后面才能进行正确的牌型比较。

7. Github的代码签入记录

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

  • 遇到的代码模块异常

    • 问题描述
      一开始算法赋予牌型的分值和牌本身大小并无联系,导致中墩和后墩出现同种牌型时(比如都是葫芦),有可能出现中墩比后墩大的情况即“相公”。
    • 做过哪些尝试
      改进了分值计算的算法,使分值计算和牌面大小有关,并加入和中墩和后墩大小的比较,若中墩分值大于后墩,则中墩和后墩交换。
    • 是否解决
      是。
    • 有何收获
      在考虑墩的大小比较时要考虑全面,不仅要考虑牌型不同时的情况,也要考虑相同牌型的情况。
  • 结对困难及解决方法

    • 问题描述
      一开始两人都没有非常擅长的领域,所以在UI和AI的任务分配时我们不知道怎么协调。
    • 做过哪些尝试
      两人都尝试着去学习和制做AI和UI部分,各取自己擅长或感兴趣的部分。
    • 是否解决
      是。
    • 有何收获
      分工搭配,干活不累!

9. 评价你的队友

  • 值得学习的地方
    不懈努力地坚持学习到天亮!!

  • 需要改进的地方
    保温杯里泡枸杞,别再熬夜伤身体

10. 学习进度条

第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累积学习耗时(小时) 重要成长
1 99 99 18 18 熟悉Axure RP用法,了解Java的trycatch语句
2 524 623 20 38 了解wx.javascript,写了一部分前端的框架
3 1072 1695 20 58 完成UI制作和算法逻辑
4 553 2248 28 86 实现接口和部分bug的修复

11.心得体会

没有什么是一杯奶茶解决不了的,熬夜之后上课还快要猝死十分精神呢!

posted @ 2019-10-15 13:23  雨霖铃0000  阅读(112)  评论(2编辑  收藏  举报