zoukankan      html  css  js  c++  java
  • 结对编程作业

    我的github项目地址 博客链接

    队友的github项目地址 博客链接

    具体分工情况表格

    任务 队友
    原型设计
    算法
    界面
    接口

    一、原型设计

    1.提供此次结对作业的设计说明,要求文字准确、样式清晰、图文并茂(多贴原型图)

    此次作业设计了4个页面,分别是主界面,开始游戏界面,游戏规则界面,联网解题界面,历史得分界面(具体内容见下图),并实现了各个界面之间的跳转。
    主界面: 是整个程序(游戏)的入口,用于链接和跳转各个界面。
    开始游戏: 是单机游戏,随机生成一个白块,并有提示功能,可玩性还行。
    游戏规则: 这个游戏的游戏规则还挺复杂,所以这个界面说明了游戏规则。
    联网解题模式: 链接postman接口,获取随机的题目,并通过AI解法解题,提交答案。
    历史得分: 针对开始游戏的那个单机游戏按步数算分,并把得分的前15个返回,简而言之,就是一个排行版。



    • 所有页面的跳转方式如下

    2.原型设计工具

    Axure Rp

    3.结对图片描述结对的过程,提供非摆拍的两人在讨论、细化和使用专用原型模型工具时的结对照片。

    题目出来的时候刚好在上课,两人对视一眼,一拍即合,默契满分,组队成功。

    4.遇到的困难及解决方法

    • 困难描述

    1.不懂原型设计是什么?
    2.只能做简单的界面,不能实现页面的跳转,其实就是不会使用Axure Rp。

    • 解决尝试

    一开始不知道原型设计的概念,后来通过百度,B站等途径了解了原型设计是产品经理的一门必修课,然后在B站两小时速成Axure Rp的使用,就可以做一个简单的还算可以的原型。

    • 是否解决

    • 有何收获

    1.了解了原型设计的重要性,扩展了知识面
    2.学会了Axure Rp的使用,可以独立做一些简单的、工程量小的原型设计

    二、AI与原型设计实现

    1.代码实现思路

    • 网络接口的使用

    •  请求接口

    import base64
    import json
    import requests
    
    def gethtml(url):
        try:
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3941.4 Safari/537.36'
            }
            r=requests.get(url,headers = headers)
            r.raise_for_status()
            r.encoding=r.apparent_encoding
            return r.text
        except:
            return ""
    if __name__ == "__main__":
        url = "http://47.102.118.1:8089/api/problem?stuid=031802433"
        # 每次请求的结果都不一样,动态变化
        text = json.loads(gethtml(url))
        img_base64 = text["img"]
        step = text["step"]
        swap = text["swap"]
        uuid = text["uuid"]
        img = base64.b64decode(img_base64)
    
    
    • 提交接口
    import json
    import requests
    def getAnswer(url):
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3941.4 Safari/537.36',
                'Content-Type': 'application/json'
            }
            r=requests.post(url,headers = headers,data = data_json)
            return r.text
    
    if __name__ == "__main__":
        url = " http://47.102.118.1:8089/api/answer"
        data = {
        "uuid":"20c8d3e27d6e4d638a1fed4218737e41",#本道题目标识
        "answer":{
            "operations": "wsaaadasdadadaws",
            "swap": [1,2]
                }
                }
        data_json = json.dumps(data)#转为json提交
        ret = getAnswer(url)
    
    • 代码组织与内部实现设计(类图)

    • 说明算法的关键与关键实现部分流程图

    •   AStart算法

    •   确定序列算法

    • 贴出你认为重要的/有价值的代码片段,并解释

    最有价值的代码片段肯定是A*算法进行自动求解,但是以因为这一部分不是我写的,所以就换成历史记录得分界面的编写,通过文件存储历史得分并取出前15名进行显示输出。

    class ThirdUi(QWidget):
        def __init__(self):
            super(ThirdUi, self).__init__()
            self.init_ui()
    
        def init_ui(self):
            self.resize(950, 950)
            self.setWindowTitle('历史得分')
            #设置背景
            window_pale = QtGui.QPalette()
            window_pale.setBrush(self.backgroundRole(), QtGui.QBrush(QtGui.QPixmap("back.jpg")))
            self.setPalette(window_pale)
    
            self.label1 = QLabel(self)
            self.label1.setGeometry(350, 50, 255, 150)
            self.label1.setText("历史得分")
            self.label1.setStyleSheet("QLabel{color:rgb(0,0,0,255);font-size:60px;font-weight:bold;font-family:楷体;}")
            self.label = QLabel(self)
            self.label.setGeometry(400, 150, 600, 800)
            with open("score.txt","r",encoding="utf-8") as fp:
                scores = fp.readlines()
                ls = []#只保留前15个记录
                for score in scores:
                    ls.append(int(score.replace('
    ', '')))
                ls = sorted(ls)
                finalstr = ''
                if len(ls)>=15:
                    for i in range(15):
                        if i<9:
                            finalstr += (str(i + 1) + '.' +"  "+ str(ls[i]) + '
    ')
                        else:
                            finalstr += (str(i+1)+'.'+" " +str(ls[i])+'
    ')
                else:
                    for i in range(len(ls)):
                        if i<9:
                            finalstr += (str(i + 1) + '.' +"  "+ str(ls[i]) + '
    ')
                        else:
                            finalstr += (str(i+1)+'.'+" " +str(ls[i])+'
    ')
                self.label.setText(finalstr)
                self.label.setStyleSheet("QLabel{color:rgb(0,0,0,255);font-size:40px;font-weight:bold;font-family:楷体;}")
            # self.label.setStyleSheet("QLabel{color:rgb(33,215,217,255)}")
            self.btn = QPushButton('返回主页面', self)
            self.btn.setGeometry(0,0, 150, 50)
            self.btn.setStyleSheet("QPushButton{color:black;font-size:20px}"
                                    "QPushButton:hover{background-color:lightgreen}"
                                    "QPushButton{background-color:lightblue}"
                                    "QPushButton{border:2px}"
                                    "QPushButton{border-radius:10px}"
                                    "QPushButton{padding:2px 4px}"
                                    )
            self.btn.clicked.connect(self.slot_btn_function)
    
        def slot_btn_function(self):
            self.hide()
            self.f = FirstUi()
            self.f.show()
    
    • 性能分析与改进

    从图可以看出本程序的时间消耗最大是pyqt5内置方法,键盘等待时间,AStart算法,pyqt5内置方法无法优化,键盘等待时间受人为因素影响不确定,所以唯一可以优化的就是AStart算法。

    • 描述你改进的思路
      通过优化AStart算法来提高程序的性能。
    •   改进前
        def solve(self):
            # self.prt2(self.mylist)
            self.goal = []
            for row in range(3):
                self.goal.append([])
                for column in range(3):
                    temp = self.numbers[row * 3 + column]
                    self.goal[row].append(temp)
            # self.prt2(self.goal)
            self.mylist = self.blocks
            if not checkNoAns(self.mylist):
                print("No Ans!")
                exit(1)
            startNum = StruNum(self.mylist, [], 0, self.goal)
            g_ListArr.append(startNum)
            cichu = 0
            while g_ListArr:
    
                nowNum = g_ListArr[0]
                g_ListArr.remove(nowNum)  # 从队列头移除
                g_readArr.append(nowNum)  # 添加到已读队列
                cichu +=1;
                if nowNum.myList == self.goal:
                    print("Find The Answer!")
                    self.ans = ""
                    while nowNum.myPreList:
                        x1, y1 = find0(nowNum.myList)
                        nowNum = nowNum.GetItsPre()
                        x2, y2 = find0(nowNum.myList)
                        if x2 > x1:
                            self.ans += "w"
                        elif x2 < x1:
                            self.ans += "s"
                        elif x2 == x1:
                            if y2 > y1:
                                self.ans += "a"
                            elif y2 < y1:
                                self.ans += "d"
                    listans = list(self.ans)
                    listans.reverse()
                    self.ans = "".join(listans)
                    print(self.ans)
                    print(cichu)
                    break
                else:
                    [idx, jdx] = nowNum.GetZeroIndex()
                    if idx - 1 >= 0:
                        upList = copy.deepcopy(nowNum.myList)
                        upList[idx][jdx] = upList[idx - 1][jdx]
                        upList[idx - 1][jdx] = 0
                        upNum = StruNum(upList, nowNum.myList, nowNum.myCost + 1, self.goal)
                        # A*算法:代价 = 到达此状态代价 + 期望到达目标节点代价
                        upNum.myCost += upNum.GetGoalCost()
                        # 如果新节点没有被走过
                        if upNum.GetListIndex(g_readArr) == -1:
                            tmpIndex = upNum.GetListIndex(g_ListArr)
                            if tmpIndex != -1:
                                # 当新节点已经出现在未读队列中,如果新节点的代价更小,则更新,否则不更新
                                if upNum.myCost < g_ListArr[tmpIndex].myCost:
                                    g_ListArr.remove(g_ListArr[tmpIndex])
                                    g_ListArr.append(upNum)
                            else:
                                g_ListArr.append(upNum)
    
                    if idx + 1 < 3:
                        downList = copy.deepcopy(nowNum.myList)
                        downList[idx][jdx] = downList[idx + 1][jdx]
                        downList[idx + 1][jdx] = 0
                        downNum = StruNum(downList, nowNum.myList, nowNum.myCost + 1, self.goal)
                        downNum.myCost += downNum.GetGoalCost()
                        # 如果新节点没有被走过
                        if downNum.GetListIndex(g_readArr) == -1:
                            tmpIndex = downNum.GetListIndex(g_ListArr)
                            if tmpIndex != -1:
                                # 当新节点已经出现在未读队列中,如果新节点的代价更小,则更新,否则不更新
                                if downNum.myCost < g_ListArr[tmpIndex].myCost:
                                    g_ListArr.remove(g_ListArr[tmpIndex])
                                    g_ListArr.append(downNum)
                            else:
                                g_ListArr.append(downNum)
    
                    if jdx - 1 >= 0:
                        leftList = copy.deepcopy(nowNum.myList)
                        leftList[idx][jdx] = leftList[idx][jdx - 1]
                        leftList[idx][jdx - 1] = 0
                        leftNum = StruNum(leftList, nowNum.myList, nowNum.myCost + 1, self.goal)
                        leftNum.myCost += leftNum.GetGoalCost()
                        # 如果新节点没有被走过
                        if leftNum.GetListIndex(g_readArr) == -1:
                            tmpIndex = leftNum.GetListIndex(g_ListArr)
                            if tmpIndex != -1:
                                # 当新节点已经出现在未读队列中,如果新节点的代价更小,则更新,否则不更新
                                if leftNum.myCost < g_ListArr[tmpIndex].myCost:
                                    g_ListArr.remove(g_ListArr[tmpIndex])
                                    g_ListArr.append(leftNum)
                            else:
                                g_ListArr.append(leftNum)
    
                    if jdx + 1 < 3:
                        rightList = copy.deepcopy(nowNum.myList)
                        rightList[idx][jdx] = rightList[idx][jdx + 1]
                        rightList[idx][jdx + 1] = 0
                        rightNum = StruNum(rightList, nowNum.myList, nowNum.myCost + 1, self.goal)
                        rightNum.myCost += rightNum.GetGoalCost()
                        # 如果新节点没有被走过
                        if rightNum.GetListIndex(g_readArr) == -1:
                            tmpIndex = rightNum.GetListIndex(g_ListArr)
                            if tmpIndex != -1:
                                # 当新节点已经出现在未读队列中,如果新节点的代价更小,则更新,否则不更新
                                if rightNum.myCost < g_ListArr[tmpIndex].myCost:
                                    g_ListArr.remove(g_ListArr[tmpIndex])
                                    g_ListArr.append(rightNum)
                            else:
                                g_ListArr.append(rightNum)
    
                    # 按照COST排序
                    g_ListArr.sort(key=takeThr)
    


    •   改进后
    def Astar(startStat):
        # open和closed存的是grid对象
        openlist = []
        closed = []
        # 初始化状态
        g = grid(startStat)
        # 检查是否有解
        if not judge(startStat, target):
            print("无解")
            exit(1)
    
        openlist.append(g)
        # time变量用于记录遍历次数
        time = 0
        # 当open表非空时进行遍历
        while openlist:
            # 根据启发函数值对open进行排序,默认升序
            openlist.sort(key=lambda G: G.F)
            # 找出启发函数值最小的进行扩展
            minFStat = openlist[0]
            # 检查是否找到解,如果找到则从头输出移动步骤
            if minFStat.H == 0:
                print("found and times:", time, "moves:", minFStat.G)
                minFStat.seeAns()
                break
    
            # 走到这里证明还没有找到解,对启发函数值最小的进行扩展
            openlist.pop(0)
            closed.append(minFStat)
            expandStats = minFStat.expand()
            # 遍历扩展出来的状态
            for stat in expandStats:
                # 将扩展出来的状态(二维列表)实例化为grid对象
                tmpG = grid(stat)
                # 指针指向父节点
                tmpG.pre = minFStat
                # 初始化时没有pre,所以G初始化时都是0
                # 在设置pre之后应该更新G和F
                tmpG.update()
                # 查看扩展出的状态是否已经存在与open或closed中
                findstat = isin(tmpG, openlist)
                findstat2 = isin(tmpG, closed)
                # 在closed中,判断是否更新
                if findstat2[0] == True and tmpG.F < closed[findstat2[1]].F:
                    closed[findstat2[1]] = tmpG
                    openlist.append(tmpG)
                    time += 1
                # 在open中,判断是否更新
                if findstat[0] == True and tmpG.F < openlist[findstat[1]].F:
                    openlist[findstat[1]] = tmpG
                    time += 1
                # tmpG状态不在open中,也不在closed中
                if findstat[0] == False and findstat2[0] == False:
                    openlist.append(tmpG)
                    time += 1
    


    从这几张性能分析图的对比可以看出,改进后的算法性能提升了将近三倍。

    • 展示性能分析图和程序中消耗最大的函数

    •   性能分析图

        程序中消耗最大的函数:pyqt5内置方法(大约占了程序的74.6%

    • 展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路

    单元测试采用AI大比拼的接口,通过返回的"success"值与True比较,如果相同则说明本题求解成功,通过单元测试,反之则未通过。具体实现代码如下:

    #coding:utf-8
    import unittest
    from AI大比拼 import *
    class MyTestCase(unittest.TestCase):
        def test1(self):
            uuid = "7aa3a255-a8a9-4314-91d8-57772d068087"
            global  answer
            answer = False
            step, swap, uuid, zuhao, listproblem, dis = jiekou.challenge(uuid)
            set(step, swap, uuid, zuhao, listproblem, dis)
            NumberHuaRong()
            jiekou.submit(uuid, operations, myswap)
            self.assertEqual(answer, True)
        def test2(self):
            uuid = "ec0dd026-3a78-4b18-971f-2b651aaa7b5f"
            global  answer
            answer = False
            step, swap, uuid, zuhao, listproblem, dis = jiekou.challenge(uuid)
            set(step, swap, uuid, zuhao, listproblem, dis)
            NumberHuaRong()
            jiekou.submit(uuid, operations, myswap)
            self.assertEqual(answer, True)
        def test3(self):
            uuid = "cac66a4d-956b-4abe-9baf-f45087a4290a"
            global  answer
            answer = False
            step, swap, uuid, zuhao, listproblem, dis = jiekou.challenge(uuid)
            set(step, swap, uuid, zuhao, listproblem, dis)
            NumberHuaRong()
            jiekou.submit(uuid, operations, myswap)
            self.assertEqual(answer, True)
    if __name__ == '__main__':
        unittest.main()
    

    2.贴出Github的代码签入记录,合理记录commit信息。






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

    • 问题描述

    在编写UI界面的过程中,华容道的界面和主界面无法进行切换,开始是想通过一个按钮来实现界面的切换,但是添加了按钮后整个游戏的九宫格布局就被毁了,而且还有可能闪退.

    • 解决尝试

    队友灵机一动,想出了通过键盘的按钮来触发界面的切换,既不会破坏布局,也可以实现切换功能,而且效果还更好。问题完美解决~~~nice

    • 是否解决

    • 有何收获

    通过这次华容道的学习,学习到了非常多的知识。比如pyqt5的以及qtDesigner的使用,在这之前,我只会用tkinter进行一些简单的GUI界面编程,这次通过pyqt5的学习,可以用之开发一些较为复杂的界面,qt不愧是GUI编程的神器。还有接口的使用,学习了使用Python提交url请求。

    4.评价你的队友。(2分)

    • 值得学习的地方

    十分感谢我无敌的队友,我生病了一段时间回来就把大部分东西都搞完了,超强的学习和实践能力是十分值得我学习的。

    • 需要改进的地方

    太优秀了,没有缺点,不用改进。

    5.提供此次结对作业的PSP和学习进度条(每周追加)

    • 学习进度条
    第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
    第一周 300 300 10 10 学会设计原型和Axure的使用,初步了解qt
    第二周 500 800 5 15 学习了一些八数码的算法
    第三周 300 1100 12 22 学习了pyqt5编写GUI界面
    第四周 300 1400 10 32 学习了接口的编写
    • PSP表格

      PSP2.1

      Personal Software Process Stages

      预估耗时(分钟)

      实际耗时(分钟)

      Planning

      计划

      70

      70

      · Estimate

      · 估计这个任务需要多少时间

      70

      70

      Development

      开发

      1030

      1750

      · Analysis

      · 需求分析 (包括学习新技术)

      300

      870

      · Design Spec

      · 生成设计文档

      200

      210

      · Design Review

      · 设计复审

      50

      40

      · Coding Standard

      · 代码规范 (为目前的开发制定合适的规范)

      20

      30

      · Design

      · 具体设计

      30

      30

      · Coding

      · 具体编码

      300

      430

      · Code Review

      · 代码复审

      30

      20

      · Test

      · 测试(自我测试,修改代码,提交修改)

      100

      120

      Reporting

      报告

      400

      440

      · Test Repor

      · 测试报告

      300

      320

      · Size Measurement

      · 计算工作量

      50

      50

      · Postmortem & Process Improvement Plan

      · 事后总结, 并提出过程改进计划

      50

      70

      · 合计

      1500

      2260

  • 相关阅读:
    《.NET深入体验与实战精要》读书体会
    为什么周易中有64卦?
    16进制与8进制之间的快速转码
    3种夸克有多少组合?
    分辨率宽高和为整千?
    abt DVD
    为什么有20种氨基酸?
    HD与BD次时代之战!
    [转载]Java一些基础问题
    [转载]Java环境变量配置
  • 原文地址:https://www.cnblogs.com/koun/p/13811227.html
Copyright © 2011-2022 走看看