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

    我的博客链接:https://www.cnblogs.com/axx4136/p/13841086.html

    我的Github链接:https://github.com/axx4136/NumberHuaRongDao.git

    队友的博客链接:https://www.cnblogs.com/kkk-home/p/13838618.html

    队友的Github链接:https://github.com/031804119/jigsaw

    具体分工

    任务 队友
    原型设计
    AI算法设计
    游戏代码
    接口与测试

    原型设计

    设计说明

    既然要设计一个游戏,最基本的肯定要有开始,退出和得分(步数),为了方便还原,将图片的原来样子也展示出来

    玩家可以通过查看栏菜单查看游戏规则和排行榜

    游戏里添加了强制交换功能,但是因为键盘不方便实现自定义调换,可能会出现无解的情况,于是就注释掉了

    因为我们的游戏界面设置的很小,所以如果要添加这么多按钮,就会显得拥挤,所以menu组件就派上了用场

    原型开发工具

    Axure Rp 8

    结对过程

    舍友两两组合

    困难方法

  • 困难描述
  • 之前从来没有接触过原型设计,对概念对操作都是一头雾水
  • 解决尝试
  • 询问往届的学长学姐,在B站上看教学视频
  • 收获与遗憾
  • 虽然刚开始都不懂,但是根据视频教学很快就能上手,基本的操作及交互动作试两下就能熟悉,而且也激发了我们对原型设计的兴趣,以后找机会会自己练一练的。然后有点尴尬的是这次作业的原型设计还是十分简陋,因为原型设计是临时学的怕在代码中实现不了。。

    AI与原型设计实现

    代码实现思路

    网络接口的使用

    用requests和BeautifulSoup处理,获取某题的Uuid,返回图片的src链接,challengeidd,强制交换的步数和强制交换的操作

    getProblem.py

    import json
    import requests
    import base64
    url ="http://47.102.118.1:8089/api/challenge/start/e9d5727c-57fa-4182-a1fd-24b43fd392ce"
    data = {
        "teamid": 53,
        "token": "99a01c39-f3ee-4967-8b5e-35cfbcfb9f7a"
    }
    r = requests.post(url,json=data)
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    dic=json.loads(r.text)
    img = base64.b64decode(dic["data"]["img"])
    Step=dic["data"]["step"]
    Swap=dic["data"]["swap"]
    Uuid=dic['uuid']
    with open("./photo.jpg", "wb") as fp:
        fp.write(img)  # 900*900

    将获取返回的Uuid和算法解出来的operations和swaplist上传

    post.py

    import json
    import requests
    import getproblem as gp
    import qipan as Qi
    url ="http://47.102.118.1:8089/api/challenge/submit"
    data = {
        "uuid": gp.Uuid,
        "teamid": 53,
        "token": "99a01c39-f3ee-4967-8b5e-35cfbcfb9f7a",
        "answer": {
            "operations": Qi.operations,
            "swap": Qi.swaplist
        }
    }
    r = requests.post(url,json=data)
    print(r.text)

    代码组织与内部实现设计

    本部分有getProblem.py,cutImage.py,find_image.py,post.py为工具类函数,用于获取题目,题目图片预处理等,还有generator.py和cutImage.py来生成用于预测代价和题目切图保存到本地文件夹.

    Prediction.py,qipan.py两个用于AI求解的函数,Prediction.py通过generator.py生成的quary表中字典代价去预测当前状态下代价最小的下一步走向,qipan.py中实现循环和强制交换,与find_image.py中其他功能性函数链接,包括判断是否无解,无解后自行交换的方法实现

    算法关键

    识别出挖空的数字,导入对应的q_tab表,每次通过棋盘当前的状态,生成0123的随机序列,0123代表上左下右,对于四个方向的操作,计算出四个方向的代价,之后返回代价列表中最小的代价对应的方向操作

    find_image.py 其中的将图片对应关系变成二维数组

    def make_qipan(m):
        sign=[1,2,3,4,5,6,7,8,9]#存储被挖空的图的位置
        blanknumber=[1,2,3,4,5,6,7,8,9]#存储被挖空的图是第几张图
        temp=[]#存储棋盘的顺序
        qipan=np.arange(1,10).reshape(3,3)#创建2维数组
        for pic2 in os.listdir('./QuestionCut'):
            for pic1 in os.listdir('./picture/' +m):
                with open ('./picture/'+m+'/'+pic1,'rb') as f1:
                    base64_f1=base64.b64encode(f1.read())
                with open ('./QuestionCut/'+pic2,'rb') as f2:
                    base64_f2=base64.b64encode(f2.read())
                if base64_f1==base64_f2:#找到切图和数据库中的对应关系
                    number=int(pic2.split('.')[0])
                    col=(number-1)%3#记录每一个问题切图的所在列
                    row=int((number-1)/3)#记录每一个问题切图的所在行
                    qipan[row][col]=pic1.split('.')[0]#对应棋盘的位置为这个图所对应数据库的图的数字
                    temp.append(int(pic1.split('.')[0]))#按顺序存到temp
                    sign.remove(number)#在存储被挖空的图的位置列表去除对应
                    blanknumber.remove(int(pic1.split('.')[0]))#在存储被挖空的图的数字列表去除对应
        qipan[int((sign[0]-1)/3)][(sign[0]-1)%3]=blanknumber[0]#令二维数组被挖空的图的位置值为0
        return temp,qipan,sign[0],blanknumber[0]#返回二维数组的一维形式temp,二维数组qipan,sign[0]为被挖空的数字的题目位置序号,blanknumber[0]为被挖空的数字

    判断逆序对的方法judgment,逆序数奇偶性的判断,需要除了空格以外的八个数的有序数列计算

    def judgment(temp):
        signal=0
        for i in range(len(temp)):
            for j in range(i+1,len(temp)):
                #计算逆序对
                if temp[i]>temp[j]:
                    signal+=1
                    #保存第一个有逆序对的数字的位置
                    if signal==1:
                        position=i
        if signal%2!=0:#逆序对为奇数则无解
            print('no way')
            return signal,position

    将二维数组转换为有序的一维数组,和judgment对接

    def turnToarray(qipan,bk):
        t=[]
        for i in range(3):
            for j in range(3):
                if qipan[i][j]!=bk:
                    t.append(qipan[i][j])
        return t
    

    性能分析

    由于强制交换的存在,代价预估预测都对当前状态进行代价分析,不会考虑利用强制交换获取捷径,所以这强制交换之前的操作可能使得交换后更加复杂或者更加简单。

    性能分析图

    项目展示测试单元

    测试接口获取题目gettest.py

    import base64
    import json
    import requests
    from PIL import Image
    def gethtml(url):
        try:
            resp = requests.request('get', url)
            resp.raise_for_status()
            resp.encoding = resp.apparent_encoding
            return resp.text
        except:
            print('err')
    def getProblem():
        url = "http://47.102.118.1:8089/api/problem?stuid=031804140"
        # 每次请求的结果都不一样,动态变化
        text = json.loads(gethtml(url))
        img_base64 = text["img"]
        step = text["step"]
        swap = text["swap"]
        uuid = text["uuid"]
        img = base64.b64decode(img_base64)
        # 获取接口的图片并写入本地
        with open("question.jpg", "wb") as fp:
            fp.write(img)  # 900*900
        return step,swap
    Step,Swap=getProblem()
    print(Swap)
    print(Step)

    测试接口提交答案posttest.py

    import json
    import requests
    import getproblem as gp
    import qipan as Qi
    url ="http://47.102.118.1:8089/api/answer"
    data = {
        "uuid": gp.Uuid,
        "answer": {
            "operations": Qi.operations,
            "swap": Qi.swaplist
        }
    }
    r = requests.post(url,json=data)
    print(r.text)

    Github代码签入记录

    模块异常

    问题描述

    强制交换后如果无解,在自行交换过后会出现两个0,即两个数字为挖空的数字,从而导致永远无解;也有交换过后没有改变逆序数的情况也是永远无解

    尝试解决

    通过对出现问题的题目二维数组进行人工复现代码,找出自行交换的下标处理需要考虑当前空格和交换格子的相对位置

    是否解决

    def swap(qipan,p,bkp):
        if bkp<=p: #空格在第一个逆序数的左边
            t = qipan[(p+1) // 3][(p+1) % 3]
            qipan[(p+1) // 3][(p+1) % 3] = qipan[(p + 2) // 3][(p + 2) % 3]
            qipan[(p + 2) // 3][(p + 2) % 3] = t
            print('swap[%d , %d]' % (p+1, p + 2))
            return p+1, p + 2
        else:
            if bkp==p+1:
                t=qipan[p//3][p%3]
                qipan[p//3][p%3]=qipan[(p+2)//3][(p+2)%3]
                qipan[(p + 2) // 3][(p + 2) % 3]=t
                print('swap[%d , %d]' % (p, p + 2))
                return p, p + 2
            else:
                t=qipan[p//3][p%3]
                qipan[p // 3][p % 3] = qipan[(p + 1) // 3][(p + 1) % 3]
                qipan[(p + 1) // 3][(p + 1) % 3] = t
                print('swap[%d , %d]' % (p, p + 1))
                return p, p + 1

    有何收获

    能解出答案了www,当时写的太过草率,重新理解以后感觉蛮好的

    .

    评价我的队友

    值得学习的地方:学习能力强,效率高

    需要改进的地方:有点懒癌:)

    PSP表格/学习进度条

    PSP Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
    Planning 计划 60 100
    Estimate 估计这个任务需要多少时间 60 100
    Development 开发 1120 1940
    Analysis 需求分析 (包括学习新技术) 400 720
    Design Spec 生成设计文档 50 80
    Design Review 设计复审 20 30
    Coding Standard 代码规范 (为目前的开发制定合适的规范) 50 50
    Design 具体设计 80 100
    Coding 具体编码 360 600
    Code Review 代码复审 120 120
    Test 测试(自我测试,修改代码,提交修改) 150 240
    Reporting 报告 110 110
    Test Repor 测试报告 60 40
    Size Measurement 计算工作量 30 40
    Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 20 30
    合计 1290 2240
    第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
    1 110 110 6 6 学会Axure的基本操作,从测试接口获取答案和上传答案
    2 340 450 16 22 掌握tkinter的基本架构,掌握广搜和循环迭代的原理
    3 350 800 10 32 游戏功能实现,内嵌AI算法,数据结构剖析,实现判断交换数据格式转换等
查看全文
  • 相关阅读:
    主攻ASP.NET.4.5.1 MVC5.0之重生:创建UIHelper通用自定义分页和选择开关与PagesHelper和IsSelect简单用法
    主攻ASP.NET.4.5.1 MVC5.0之重生:系统角色与权限(二)
    @MarkFan 口语练习录音 20140423 [风雨哈佛路.Homeless To Harvard口语录音]
    主攻ASP.NET.4.5.1 MVC5.0之重生:系统角色与权限(一)
    离乡与理想 小样
    主攻ASP.NET.4.5.1 MVC5.0之重生:空地搭建一个包含 Ninject框架 项目
    震撼全世界的一块墓碑
    @MarkFan 口语练习录音 20140415 [MDL演讲口语录音]
    PHP预编译处理技术简介
    事物控制之保存点
  • 原文地址:https://www.cnblogs.com/axx4136/p/13841086.html
  • Copyright © 2011-2022 走看看