软工导论-3-记忆广度(微信小程序)的设计开发实装
[TOC]
记忆广度-微信小程序开发-个人总结
| 博客班级 | https://edu.cnblogs.com/campus/zjcsxy/SE2020 |
|---|---|
| 作业要求 | https://edu.cnblogs.com/campus/zjcsxy/SE2020/homework/11633 |
| 班级 | 计算机1803 |
| 姓名 | 章一砚 |
| 学号 | 31801146 |
记忆广度是什么:游戏设计与规则介绍
- 规则:给出一个用方块拼接成的图形,每个方块中有一个数字,图形显示的时间根据难度设定,三个难度等级设定的时间分别为5秒,10秒,15秒,图形显示结束后打乱方块顺序,要求被测者将方块拖回原来的位置。
结束条件:连续做错3题或完成全部的题目;
每题时间限制:90秒;
评分:做对1题得1分,共18题,最高分为18分
难度一:由五个数字方块组成的图形
难度二:由六个数字方块组成的图形
难度三:由七个数字方块组成的图形 - GIF演示
游戏设计 - 界面:
- 棋盘:用于摆放方格。我们设计一个 4 × 4 的棋盘,用于摆放方格。(之后,我们会使用“棋子”这个称呼来代替方格)
- 方格(棋子):方格应该有三种状态【空白格子、棋盘底色格子、有数字的格子】
- 方格(棋子)拼接成的图形:应该是在这个 4 × 4 的棋盘中随机生成的一个图形
- 方格(棋子)待选区:将之前在棋盘中出现过的数字方格打乱顺序,放置在棋盘下方的待选区。
- 状态栏:包括
- 当前游戏状态【等待开始、请记忆棋盘、请拖动棋子(等待提交答案)】
- 当前游戏进度【第 1 / 6 关】
- 当前环节倒计时【还剩 … 秒】
- 按钮组:至少有一个 “提交答案” 的按钮,用于在等待用户拖动棋子的倒计时中,让用户主动提交答案,进入下一个环节。
游戏设计 - 数据:
- 棋盘大小
board_size:设定为 4 × 4 即可,没有变化的必要 - 棋子个数
level:有数字的、需要记忆的棋子个数 —— 暂定为 5 6 7 个,需要支持使用方便的参数进行动态的修改。 - 记忆耗时
level_time:对于不同的棋子个数,记忆的时间暂定为 —— 5 10 15 秒,需要支持使用方便的参数进行动态的修改。 - 棋子拖动耗时常量即可:最多不超过10个棋子需要被拖动。为保险起见,设定30秒用于等待拖动,绰绰有余。
- 棋盘中的每个棋子是什么:
- 使用一个
Number[] board_num[16]来保存。 - 数组元素为 -1 的,应该是空白棋子,不然,就是数字棋子。
- 使用一个
- 棋子本身的相关信息:
- 棋子是哪个数字对应的棋子——数字本身
- 棋子在本次游戏中,被放在了棋盘的哪个位置
- 可以从
board_num[16]中遍历查得。 - 但是为了方便,不如再设计一个数组
chess_index[level]第 i 个棋子,在本局中的初始位置是chess_index[i]
- 可以从
- 棋子现在被放在了哪个位置
chess_nowAt[16]-1表示棋子正处于待选区- 否则,表示棋子正处于棋盘的某个位置
- 如果
chess_index[i] = chess_nowAt[chess_index[i]]则棋子位置符合答案要求
- 棋子动态拖动需要的相关信息:
chess_start[16]用于保存棋子初始位置。chess_move[16]用于保存棋子位移。- 棋子初始位置:
- 这个初始位置指的是棋子在待选区时的初始位置。
- 棋子位移:
- 这个位移指的是棋子当前位置和在待选区的位置的相对位移。
- 棋子当前位置:
- 棋子初始位置 + 棋子位移 = 棋子当前位置
pos_table[16]用于保存棋盘中的16个格子各自的坐标位置。- 当需要获取棋子当前位置是否是棋盘中的某个格子时
- 遍历
pos_table[16],与棋子当前位置进行比较 - 误差允许则返回匹配到的位置在
pos_table[16]中的索引值 - 否则,返回
-1
chess_zindex[16]用于保存棋子的CSS属性z-index的值- 我们希望棋子在被拖动时,应该是 z-index 值最大的,不会被别的UI元素覆盖遮挡住
各功能 具体实现 复盘
生成一个随机的棋盘
初级需求
- 这个棋盘应该是一个长为 16 的数字数组
- 这个数组中 有
level个不是 -1 的数- 不是 -1 的数,包括 1,2,3,4,5,6,7,8,9
- 注意,不含 0
- 棋盘应该是随机的
初级需求的实现
原地随机一个数组
// 有很多种写法,反正,写起来不难 |
获取初级需求的一个随机棋盘
/** |
进阶需求
- 按初级需求中的方式生成的棋盘,是随机的。
- 这样的随机同时会导致棋子在棋盘上的散乱分布。
- 作为记忆广度的棋盘,我们不希望棋子过于散乱分布。
- 我们希望棋子尽量是一定程度上连续的。
进阶需求的实现
检查棋子图形是否足够连续
- 检查棋子连续性,其实也就是,检查棋子是不是”连通图“
- 用 BFS/DFS 遍历之即可
/** |
调整棋盘使图形聚拢
- 将整个 4 × 4 理解为 中间的一个 2 × 2 和外面的一圈
- 遍历外面的一圈棋子,尝试让他们向内移动一格
- 如果外圈棋子内的格子是有棋子的,则不移动
- 否则,向内移动一格
/** |
组合棋盘聚拢和连通性检查
- 遍历并尝试移动一遍以后,再次检查棋盘是否足够连通
- 如果还没有,那就再遍历一轮并尝试移动
- 如此,往复几轮,基本上能让棋盘成为连通图
- 既使还没完全连通,也问题不大了(不是过于散乱了)
/** |
棋盘大小及棋子大小的动态设定
- 这个棋盘的棋子个数是固定 4 × 4 的
- 因此,棋子大小只与屏幕大小有关
- 棋盘是方形的,长度和宽度相同
- 按照团队协作规范,棋盘宽度设定为屏幕宽度的80%
/* 获取设备屏幕大小 */ |
棋子可拖拽的实现
棋子的定位由 left 和 top 实现
若 left. top 的是0,则意味着棋子在一开始的位置,没动。
棋子样式(WXML)属性值
style="z-index:{{chess_zindex[item]}};left:{{chess_move[item].left}}px;top:{{chess_move[item].top}}px;"WX 的拖拽事件,可以在WXML中设置属性值传递进
event的dataset
<view |
棋子的整个拖拽过程分为三部分
触摸开始
catchtouchstart="moveStart"
- 如果发现棋子是第一次被触摸(
chess_start[who]的 left 和 top 都是 0) - 那么获取当前触摸事件的被点击对象的位置,存储进
chess_start[who] - 同时,为了让被拖动的棋子元素是是浮动在上方,所以设一个大一点的 z-index 值
/** |
触摸移动中
catchtouchmove="handleMove"
- 通过
event.currentTarget.dataset.who得知现在是哪个棋子被拖动了 - 通过
this.data.chess_start[who]得知这个棋子一开始的初始坐标,便于后面计算位置偏移量 - 通过
event.changedTouches[0].pageX得知本次触摸点的 X 坐标。Y 坐标同理。 - 检查这个坐标是否符合棋盘某个格子的要求
- 若符合要求,则,设置位移为格子坐标减去棋子初始坐标
- 不符合要求,则,设置位移为当前触摸坐标减去棋子初始坐标
- 位移的更新到
chess_move[who],实际效果就体现为棋子被手指拖着到哪就到哪
触摸结束
catchtouchend="moveEnd"
- 和之前同理,从
event中取数据,检查坐标是否符合棋盘某个格子的要求- 若符合要求,则,啥也不做
- 不符合要求,则,设置位移为
{left:0, top:0}使棋子回到待选区
- 拖动已经结束了,z-index 可以调回来,从200改回100
棋盘各个格子的初始位置的读取
- 用微信提供的查询API,获取每个格子节点
- 遍历得到的节点序列,并获取其位置,然后存储
- 最重要的是:
- 因为棋盘有一个入场加载动画是微信自带的
- 为了保证获取到的棋盘是真的棋盘
- 而不是动画中飞到半路的棋盘
- 我们设置一个两秒的延时
- 延时以后再进行查询
/* 延迟两秒后再更新棋盘位置表,避免出现错误 */ |
最后总结
最后实装的主要内容就在这里了。其实中间还有一些失败的技术探索,各种半成品。真正花了大量时间的就是这些爬坑的过程。