结对编程作业
一、团队简介
团队成员 | 具体分工 | GitHub地址 | 博客园地址 |
---|---|---|---|
谈世宏 | AI算法、代码测试 | 算法部分 | 博客园 |
苏炜斌 | 原型设计、原型实现 | 原型部分 | 博客园 |
二、原型设计
使用工具
原型设计工具采用的是Balsamiq Mockup,选用它的原因是因为非常简单便捷,入手简单,但比较坑的是它不能直接导出HTML格式(最后才发现)
作品设计说明
因为是原型设计,所以。。。就做的比较啊。。。
文字说明在截图中右侧
1)启动界面
2)游戏首页
3)历史记录界面
4)游戏界面
5)AI演示界面
原型设计讨论图
遇到的问题
一开始做原型设计是打算用Axure Rp,下载之后感觉一点难搞,然后又看了推荐给的几个原型设计软件,看了网上的评论,讨论之后,觉得Balsamiq Mockup挺不错的,但还是想继续吐槽,为什么不加个导出HTML的功能???虽然我用的不是正版的
原型设计的实现
游戏简介
原型设计的实现采用的是用Andriod Studio写一个小游戏,在这个拼图小游戏中,可以通过游戏首页点击“开始游戏”进入游戏,即可开始拼图游戏,在游戏界面可以点击“重新开始”重新开始游戏,在游戏界面还会记录步数和记录时间,如果完成了拼图,就会将这些数据存如数据库。还可以点击“AI演示”进入AI演示界面,点击“演示”,AI开始拼图,每隔0.5s移动一步。历史记录页面记录了完成拼图的时间,步数,与完成游戏的具体时间日期。
1)原型实现的思路
2)原型实现
1.游戏启动界面
虽然觉得游戏启动界面不是非常必要但是讨论后还是加了这个界面
2.游戏首页
游戏的首页做得比较简约,就只有两个按钮,用户可以通过按钮进入游戏,或者查看历史记录
两个按钮都做了跳转功能可以从一个activity到另一个activity
(部分实现代码)
3.游戏主界面
游戏的主界面分为两个区域,一个是显示原图,和时间步数的区域,一个是显示拼图控件的区域,用户可以通过点击图片,实现移动拼图,或者点击重新开始,或者点击“AI演示”看AI演示如何完成拼图
完成拼图是会提出提示框
(部分实现代码)
当用户完成拼图后,系统会保存用户游戏数据,这部分功能通过Andiord Studio 的SQLite数据库实现,通过建立一个数据库来保存数据(具体在历史记录部分讲述)
(插入数据实现的代码)
4.AI演示部分
该部分使用AI将随机打乱的图片还原,演示给用户如何完成拼图,每0.5s移动一格
(部分实现代码)
eightpuzzless()为解出拼图步骤的AI算法,在这部分挺搞人的,为了每0.5s显示移动一步,在网上找了许多的代码。大部分都不行,最后找到了一篇大佬的博客解决了问题。
5.历史记录
历史记录用的是Android Studio 的SQLite数据库,建立了一个数据库记录用户数据,并将游戏结果显示出来
(部分实现代码)
用了RecyclerView来显示数据
遇到的困难及解决方法
1.在这次原型的实现中遇到了不少问题,刚开始想用Pygame来写游戏,但是讨论后觉得Pygame的界面可能比较难处理,选择了用Android Studio来开发游戏,虽然没用过,但当成了一次挑战,结果把自己搞得差点没了,最后结果还算满意。
2.在AI演示部分,每隔0.5s移动一步的实现卡了很久,查阅了网上的资料才解决问题
3.在游戏界面的优化上,想了较长的时间,刚开始的界面是真的不好看
4.结对的问题:分工过于明确,没能很好体现合作,觉得更多一点交叉会更好,表达不明确,讨论的效率有时候不高
代码签入(本人/部分)
三、AI与原型设计实现
1.代码实现思路
(1)网络接口的使用
本次网络接口是通过python的requests实现的,直接调用库不要太舒服,简单好用,直接上代码!
接受题目请求
import requests
request_url = 'http://47.102.118.1:8089/api/challenge/start/'+'e9d5727c-57fa-4182-a1fd-24b43fd392ce'#后面需要改动加上challenge-uuid
#队伍信息
request_dic['teamid'] = 15
request_dic['token'] = '4e717b20-c22f-48e9-b943-a7ebd4b58436'
headers = {'content-type': "application/json"}
response = requests.post(request_url, data=json.dumps(request_dic),headers=headers)
response = json.loads(response.text)#json数据转为字典
print("start:",response)
发送答案请求
send_url = 'http://47.102.118.1:8089/api/challenge/submit'
headers = {'content-type': "application/json"}
response = requests.post(send_url, data=json.dumps(send_dic),headers=headers)
response = json.loads(response.text)#json数据转为字典
2.代码组织与内部实现设计
3.算法的关键与关键实现部分流程图
4.重要的/有价值的代码片段
def AStar1(init,space_location):
# 边缘队列初始已有源状态节点
queue = Queue()
visit = {} # 访问过的状态表
node = Node(init,'',space_location)
queue.put(node)#
visit[node.state] = node.action#
count = 0 # 循环次数
# 队列没有元素则查找失败
while not queue.empty():
# 获取拥有最小估计距离的节点索引
node = queue.get()#0.35
count += 1
# 扩展当前节点
for act in GetActions(node.state,node.space):
# 获取此操作下到达的状态节点并将其加入边缘队列中
if(act == 'a'):
near = Node(a(node.state,node.space), node.action + act, node.space)
elif(act == 'w'):
near = Node(w(node.state,node.space), node.action + act, node.space)
elif(act == 's'):
near = Node(s(node.state,node.space), node.action + act, node.space)
elif(act == 'd'):
near = Node(d(node.state,node.space), node.action + act, node.space)
if not visit.__contains__(near.state):
queue.put(near)
visit[near.state] = near.action
这部分是实现bfs的关键代码,先构造一个队列,第一次将初始状态打入队列中,开始队列的循环,每次循环都会将队首状态取出,根据当前节点向周围扩展,w、a、s、d分别是我写的函数,分别可以将白方块向上、向左、向下、向右移动,Node则是一个结构体,再通过一个字典将每个已经经历过的状态记录下来(同样的坑不能掉第二次),就能获得当前节点能够跑到的所有状态啦!
if after_operations != '' :
tmp_str = after_operations[::-1]
s = ''
for i in tmp_str:
if(i == 'w'): s+='s'
elif(i=='s'): s+='w'
elif(i=='a'): s+='d'
elif(i=='d'): s+='a'
after_operations = s
这部分是在进行强制转换后,因为bfs是对目标状态进的扩展,对目标节点进行bfs其实就是将目标状态跑到其他的状态,因此需要将操作字符进行反转,操作数也要改成相反的方向。
5.性能分析与改进
(1)性能分析
bfs是将当前状态所有能够跑到的状态记录下来,根据逆序数奇偶性,有一半状态是跑不到,故每次bfs实际要循环 9!/2 =181400,然后又想到python中字典的搜索时间为O(1),故这个算法在我看来会跑的非常快。然而只是跑了一次,我竟然就是花费了十秒。但一个重大发现就是,发现字典并没有只花费O(1)的时间,在每次在字典中添加状态和检查字典中是否有这个状态竟然还是能有0.5s,搜索后发现python的字典是hash原理,那唯一一种解释便是哈希冲突太多了。还有一个时间消耗比较多的便是结点的构造,每次构造一个新的结构体状态都会花费不少的时间,占据了我消耗时间的大部分。
(2)改进
我在测试各个板块花费的时间时候,先是去掉了一些没必要的循环(花了好长时间org),减少了结构体中的元素个数,算法花费的时间也渐渐少了,。
可以看到花费时间比较多的还是bfs算法,但调用的都是python里面的库和自带的字典,实在让我很难再改进。
6.GitHub代码签入记录
7.遇到的代码模块异常或结对困难及解决方法
(1)
问题描述:题目理解的错误,强制交换的是两个方块,不是这两个数字
解决尝试:抓紧时间,疯狂找bug,和队友讨论后发现是自己理解错误
是否解决:是
收获:遇到意外情况不能太慌乱,与队友一起冷静解决问题,这不是一个人的战斗
(2)
问题描述:算法时间跑的过长并找不到办法化解
解决尝试:找百度,问大佬
是否解决:是
收获:大佬之所以能成为大佬,也有可能是他们掌握了你们还没掌握的算法
8.评价我的队友
(1)值得学习的地方:心态良好,UI设计效率高,游戏界面的设计精美,沉浸式学习可以不受外界干扰。
(2)需要改进的地方:对一些细节的把控不是很好。
9.PSP和学习进度条
(1)学习进度条
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
1 | 100 | 100 | 10 | 10 | 学习如何访问接口、切图片、图片配对 |
2 | 550 | 650 | 15 | 25 | 开始了解并逐渐掌握了A*算法、字典的基本操作 |
3 | 400 | 1050 | 18 | 43 | 学习了bfs算法,学着分析性能并改进算法 |
4 | 300 | 1350 | 18 | 61 | 对已经写好的代码根据AI大比拼结果改进 |
(2)PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 80 | 80 |
Estimate | 估计这个任务需要多少时间 | 70 | 70 |
Development | 开发 | 140 | 160 |
Analysis | 需求分析 (包括学习新技术) | 400 | 500 |
Design Spec | 生成设计文档 | 50 | 50 |
Design Review | 设计复审 | 40 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 20 |
Design | 具体设计 | 120 | 150 |
Coding | 具体编码 | 600 | 900 |
Code Review | 代码复审 | 60 | 90 |
Test | 测试(自我测试,修改代码,提交修改) | 60 | 80 |
Reporting | 报告 | 120 | 180 |
Test Repor | 测试报告 | 60 | 120 |
Size Measurement | 计算工作量 | 30 | 30 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 30 |
合计 | 1890 | 2490 |