结对编程作业

结对成员

  • 031802501 蔡震泽 博文地址 GitHub地址

  • 031802531 王昱 博文地址 GitHub地址

    成员 分工
    蔡震泽 原型设计、AI
    王昱 原型设计实现、AI

    2.1-原型设计

    2.1.1-流程图

    2.1.1-原型图

    我们整体以水墨风格设计了图片华容道,其界面如下:

    1.开始界面

    在开始界面,玩家可以进行继续下一步游戏进行登入,或者注册,或者更改游戏设置,或者退出游戏

    2.登入界面及注册

    玩家输入账号密码即可登入游戏


    3.系统设置界面

    玩家可以对音乐,音效进行设置

    4.游戏菜单

    在此界面,玩家可以查看自己的排行榜和进入游戏

    5.游戏界面

    玩家在此进行游戏,有记录时间与步数

    6.暂停界面

    在对战界面时,可以选择暂停功能

    7.胜利

    如若玩家成功完成华容道,则会出现胜利界面,有着耗费的步数和时间

    8.排行榜

    玩家可在此查看排行前列的玩家

    2.1.2-开发工具

    Axure Rp 9、 photoshop

    2.1.3-结对图

    2.1.4-遇到的困难及解决方法

    问题一:

    困难描述:由于之前的作业都是编程作业,第一次接触原型模型设计的题目,一开始有点不知所措。

    解决尝试:通过百度,查阅资料,以及观看视频来通过对原型模型的了解,经过几天的摸索,对这方面也有了一点的了解。

    是否解决:

    问题二:

    困难描述:第一次使用Axure,对于很多功能都还不熟悉
    解决尝试:依然还是通过百度,上B站看教程来自学
    是否解决:暂时解决

    问题三:

    困难描述:原型设计需要有很多的图片素材
    解决尝试:查阅了大量的素材,才找到几张觉得还不错的素材,有时候甚至自己都想用PS弄素材,但无奈自己不会PS
    是否解决:

    收获:

    这次是结对作业,所以经过这一段时间的学习,和队友的合作更加紧密,关系更加密切,交流得更多。初次体会到了一个软件的设计过程,以及团队合作的重要性。

    2.2 - AI与原型设计实现

    2.2.1-代码实现思路

    网络接口的使用

    网络接口是使用python的requests模块实现的,requests在python内置模块的基础上进行了高度的封装,所以使用方法十分简单。

    GET请求

    import requests
    
    json_url = 'http://47.102.118.1:8089/api/teamdetail/48'
    
    req = requests.get(json_url)
    
    file_requests = req.json()
    

    POST请求

    import requests
    
    import json
    
    json_url = 'http://47.102.118.1:8089/api/challenge/start/321a5671-8bfa-4664-8986-fc7a413fa540'
    
    data = json.dumps({
    
      "teamid": 48,
    
      "token": "396e1989-984d-4777-98fa-1907fd2072bf"
    
    })
    
    r=requests.post(json_url, data=data, headers={'Content-Type': 'application/json'})
    
    file_requests = r.json()
    
    代码组织与内部实现设计(类图)

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

    算法的关键是如何应对强制交换的问题,以及无解状态的处理。实现流程图如下:

    重要代码片段展示及解析

    由于BFS实现比较简单自己太菜,没有特别复杂的代码片段。这里我展示一下BFS里面比较核心的一段代码,就是move操作的实现

      def move(self,qi,blank,dire,level, path): 
      
      	 '''将空图blank进行移动,
      	 	qi是当前状态(用字符串存储),
      	 	blank是空图所在位置,
      	 	dire是移动方向,
      	 	level是当前步数
      	 	path是从原状态到当前状态的移动序列'''
    
    ​    add = 0
    ​    if dire == 'a':
    ​    	add = -1
    ​    elif dire == 'w':
    ​       add = -(self.n)
    ​    elif dire == 's':
    ​       add = self.n
    ​    elif dire == 'd':
    ​       add = 1
    ​ 	 x = blank + add	#x为blank经过移动后的位置
    	 #越界判断
    ​    if x<0 or x>=self.N or blank==x:	
    ​       return False
    ​    if abs(blank%self.n-x%self.n)>1:
    ​       return False
    	 #生成移动后的状态
    ​    if blank<x:
    ​       temp=qi[:blank]+qi[x]+qi[blank+1:x]+qi[blank]+qi[x+1:]
    ​    else:
    ​       temp=qi[:x]+qi[blank]+qi[x+1:blank]+qi[x]+qi[blank+1:]
    	 #该状态之前已经走到过,舍弃
    ​    if temp in self.dict:
    ​       return False
    	 #更新队列
    ​    self.dict[temp]=level+1
    ​    self.dict_path[temp] = path + dire
    ​    self.que_qi=[temp]+self.que_qi
    ​    self.que_bk=[x]+self.que_bk
    ​    self.que_lv=[level+1]+self.que_lv
    ​    self.que_path=['{0}{1}'.format(path, dire)]+self.que_path	#注意要记录下移动序列
    	 #如果已经完成,则结束寻路
    ​    if temp == self.fin_map:	
    ​       self.end = 1
    ​       self.ans = '{0}{1}'.format(path, dire)
    ​    return True
    
    性能分析与改进

    ​ 相比于A*和DFS,BFS能够保证最终答案是最优解,所以比较符合题目的要求。但是BFS的时间复杂度是比较高的,所以当完成拼图所需要的路径较大时,耗时也会急剧增加。BFS里面耗时占比最大的两个分别是判重和移动,这里判重是通过记录走过的状态再加上"in"操作实现的。移动操作已经通过将状态转换为字符串进行了优化,未来的改进可能会集中在判重这一块上。

    改进的思路

    ​ 在洛谷OJ上面看到了八数码难题这道题,有些大佬使用了双向BFS来解决,时间复杂度得到了极大的降低,但是实现的思路还没有完全理解,再加上由于强制调换带来的一些困难,暂时没有往这个方向上做改进。但是在判重的问题上却给了我很大的启示,如果能够将每个状态对应一个hash值,就能够直接将判重的时间复杂度将为O(1)。这里我参考了关于“康托展开”的相关知识,通过康托展开值映射到不同的状态上,而且无需占用很大的地址空间。

    性能分析图

    ​ 可以看到耗时最大的就是move函数了,之前也在前面分析了对应代码以及相应的改进方案。还有一个耗时占比较大的是将原始图片转换为对应矩阵,主要是图像的对比识别比较花时间,但这个用了别人的库,就没办法改进啦。

    2.2.2-代码签入记录

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

    问题一:

    困难描述:不知道如何传数据到api,传什么类型的数据,收到什么类型的数据
    解决尝试:通过网上查资料,问同学,一步步尝试,最终还是将接口连上了
    收获:学会了如何使用python的requests模块

    问题二:

    困难描述:异常是移动序列的顺序被打乱。本来是不知道顺序乱了,只是手工检查后发现移动序列不正确,在后面调试中把限制深度缩小到2,这才意识到是顺序乱了。
    解决尝试:经过检查发现是字符串拼接的时候出错,查阅资料后了解到,如果使用“+”运算来连接字符串可能会出现顺序错误,于是使用了格式化的方式来进行字符串拼接,解决了这一问题。
    收获:从这个错误中学习到了python的格式化输出方式,这在处理多个不同类型的数据输出时能起到很大的便利。

    问题三:

    困难描述:异常是出现在自由交换的时候,一旦需要用到自由调换时,答案一定都是错误的。我将实现自由交换的代码封装成一个函数,输入初始状态和目标状态,用两层循环遍历所有可能的交换,将有解的交换输出。但是我误以为在python中,列表作为函数参数是值传递的方式,实际上进行遍历的时候,列表已经发生了变化,而我却在函数返回交换序列后再次对列表进行了交换。
    解决尝试:至于我是怎么发现这个问题的嘛......可能人在疲倦的时候更容易灵光一现?由于前一天晚上改算法改到两点都没出结果,上课时昏昏欲睡的我脑子里还是一直装着这个问题,结果突然就想到了这个点......于是之后我又去详细了解了python关于函数的知识,看来基础还是不够牢固呀。
    收获:顺带学习了python的函数参数的各种用法

    2.2.4-评价你的队友

    值得学习的地方:

    震泽哥真的全能,Axure、PS、Java、Python全都会,原型设计直接带飞。

    需要改进的地方:

    感觉震泽哥可能细节上考虑得不太周全,设计算法时有些情况没有注意到,不过不是常说成大事者不拘小节嘛O(∩_∩)O。

    2.2.5-PSP表和学习进度条

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

第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
1 0 0 10 10 熟悉了pyame的基本开发框架,学习了如何以面向对象的思想组织游戏代码
2 357 357 28 38 在实际操作中掌握了如何监听游戏事件的发生以及响应处理
3 520 877 10 48 学习了使用python的PIL库进行图像处理
4 395 1272 35 83 掌握了如何利用python的requests模块设计网络接口

posted @ 2020-10-19 22:26  幸村家的橙子  阅读(127)  评论(0编辑  收藏  举报