电玩圈游戏网 搜一搜

安卓手游去频道 >

角色扮演 射击枪战 棋牌卡牌 体育运动 角色扮演 赛车竞速 休闲益智 音乐舞蹈 模拟经营 战棋塔防 推理解谜 策略战争

安卓应用去频道 >

社交通讯 系统工具 影音视听 拍摄美化 效率办公 学习教育 生活服务 旅游出行 资讯阅读 金融理财 网络购物 游戏助手

游戏视频去频道 >

动作冒险 射击枪战 棋牌卡牌 体育运动 角色扮演 赛车竞速 音乐舞蹈 模拟经营 战棋塔防 推理解谜 策略战争 休闲益智

资讯攻略去频道 >

手游资讯 手游攻略 手游问答 游戏资讯 游戏杂谈 游戏攻略 软件教程 软件资讯

专题合集去频道 >

游戏专题 应用专题

排行榜单去频道 >

游戏排行 应用排行
首页 游戏 应用 视频 资讯 专题 榜单

首页>资讯>游戏攻略>深圳SHENZHENIO阿瓦隆城第9关细胞支架模型攻略

深圳SHENZHENIO阿瓦隆城第9关细胞支架模型攻略

作者:佚名来源:百度2022/07/11

深圳IO是一款硬核的编程游戏,有着严谨的游戏内容,那么一起来看看阿瓦隆城第9关细胞支架模型的攻略吧。

关卡展示

本关的【数据】输入会不定期地发送一些数据包。有时是由 6 位数字组成的数据包,收到它后需要控制右侧的 3D 打印机打出一个 6x6 的矩阵模型;有时只有一个 -1,收到它后需要控制 3D 打印机回到原点。具体打印的内容我们需要参照数据手册:

本数据手册有一处印刷错误,第 4 行最后的英文字母 y 应该改为希腊字母 ψ。

我们每从【数据】输入端口中收到一个 0~8 的数字时,就需要对照着以上表格打印出矩阵的一行。而且,为了节约时间,打印机按照 Z 字形移动,也就是:打印第奇数行时,打印机从左到右移动;打印第偶数行时,打印机从右到左移动。而不是像打字机一样,每到新的一行,就回到最左边。下面的动图演示了打印机在收到 214426 这个数据包后的工作过程:

电机初始位于 (0, 0) 处;

收到第一个数字 2 时,对照数据表里的行 2,从左到右打印六个 β(青绿色),然后电机上移一格,此时电机位于 (1, 5) 处;

收到第二个数字 1 时,对照数据表里的行 1,从右到左打印六个 α(梅红色),然后电机上移一格。此时电机位于 (2, 0) 处;

收到第三个数字 4 时,对照数据表里的行 4,从左到右依次打印 ψ(蛋黄色)、α(梅红色)、α(梅红色)、ψ(蛋黄色)、α(梅红色)、ψ(蛋黄色),然后电机上移一格。此时电机位于 (3, 5) 处;

收到第四个数字 4 时,对照数据表里的行 4,从右到左依次打印 ψ(蛋黄色)、α(梅红色)、ψ(蛋黄色)、α(梅红色)、α(梅红色)、ψ(蛋黄色),然后电机上移一格。此时电机位于 (4, 0) 处;

收到第五个数字 2 时,对照数据表里的行 2,从左到右打印六个 β(青绿色),然后电机上移一格,此时电机位于 (5, 5) 处;

收到第六个数字 6 时,对照数据表里的行 6,从右到左依次打印 ψ(蛋黄色)、空白、ψ(淡黄色)、空白、空白、ψ(蛋黄色),然后电机上移一格。此时电机位于 (6, 0) 处;

收到最后的 -1 时,电机向下移动 6 格,回到原点 (0, 0)。

本关需要 6 块芯片分工合作!电路图如下:

首先看最靠左的芯片。它是唯一和【数据】输入相连接的芯片,因此它是 1 号芯片。我们首先写它的代码:

收到行号后(slx x1),将收到的行号 ×2 后(mov x1 acc, add acc)给中间的 2 号芯片,以及右边控制电机移动的 4、5 号芯片各发一份(mov acc x0, mov acc x2, mov acc x3)。做完这些后,休眠 6 秒(slp 6)。至于为什么要将数字 ×2,以及为什么要休眠 6 秒,我们后面再说。

然后我们看位于正中央的,记录行号和电机实时 X 坐标的 2 号芯片的代码:

收到广播信号后(slx x1),将扩大 2 倍后的行号同步到 p0 口中供下方的 3 号芯片使用(mov x1 p0)。然后开始计算电机的实时 X 坐标。我们说过,电机既可能从左向右移动,也可能从右向左移动。电机的移动方向取决于移动前的初始 X 坐标。初始坐标为 0 时,本行的 X 从 0 移动到 5,是从左向右移动的模式;初始坐标为 5 时,本行的 X 从 5 移动到 0,是从右向左移动的模式。所以我们首先判断初始 X 坐标的值是 0 还是 5(tgt acc 2),对应地激活 + - 中的一个代码块。

初始 X 坐标是 0 时,激活 - 号代码块,采用从左向右移动的模式:将当前 X 坐标发给 3 号芯片(mov acc x2),睡一秒后(slp 1)检查 X 是否小于 5(- tcp acc 5)。小于 5 时令 acc +1(- add 1),并跳到第 4 行继续给 3 号芯片发坐标(- jmp 4),直到 X = 5 为止,关闭一切 + - 号指令,跳回到第 1 行等待下一行的任务。

初始 X 坐标是 5 时,激活 + 号代码块,采用从右向左移动的模式:将当前 X 坐标发给 3 号芯片(mov acc x2),睡一秒后(slp 1)检查 X 是否大于 0(+ tcp acc 0)。大于 0 时令 acc -1(+ sub 1),并跳到第 4 行继续给 3 号芯片发坐标(+ jmp 4),直到 X = 0 为止,关闭一切 + - 号指令,跳回到第 1 行等待下一行的任务。

2 号芯片是一个纯工具芯片,它仅仅在为 3 号芯片提供行号和 X 坐标的数据。

下面来看位于左下方的,随时查询待打印细胞的 3 号芯片的代码:

现在是时候解释为什么 1 号芯片收到行号后要将它 ×2 了。

数据手册里提供了 9 种细胞模型,行号为 0~8。如果我们一位数一位数地存储,那要存 6×9=54 个数字,要四块 ROM 才放得下!而我们的线路板面积只有这么点大,根本没有空间放得下四块 ROM;即使勉强放得下,也没法和这么多 ROM 同时进行通讯。因此我们必须要使用压缩的方式来存储,比如用三位数来存储连续的三种材料,这样一个细胞模型用 2 格 ROM 空间,共 6 位数,占用空间就小得多了。

做了这样的状态压缩后,9 种细胞模型需要 2×9=18 个数字,一块 ROM 还是放不下。但我们观察数据手册发现:

前 3 行的 6 格内容都是一样的,这样一来前 3 行完全没必要往 ROM 里存,只存剩下的 6 格内容就好。至此,剩下的 6 种细胞模型就只占用了 2×6=12 个数字,终于可以完美地放在一块 ROM 里了。

1 号芯片之所以要将行号 ×2,是因为(除前 3 行外的)每一行的细胞模型都需要占用两格 ROM 空间来存储。如果将 6 位数存在【行号】开头的两格 ROM 空间里,那么相邻行之间会有冲突。只有将 6 位数存在【行号 ×2】开头的两格 ROM 空间里时,才能解决相邻行之间的位置冲突。1 号芯片将行号 ×2 后,本质上是将【行号】转换成了【ROM 地址】。3 号芯片需要的正是后者。

此时我们来观察一下 ROM:

第 0~2 行的细胞模型并没有存储在 ROM 中,我们需要从第 3 行(即 6 号地址空间)开始看。第 3 行对应的地址 6、7 存储的是 424242 这样的六位数,在数据表里对应着 αβαβαβ 的细胞模型。看到这,你可能会想当然地以为 4 是 α, 2 是 β。但我要告诉你,不是的。我们接着往下看:第 4 行对应的地址 8、9 存储的是 626226 这样的六位数,在数据表里对应着 ψααψαψ 的细胞模型。

这里你可能会觉得奇怪了,2 到底对应谁,怎么跟三种希腊字母都对应了?其实,这里一行细胞模型的每一格,是跟一个六位数【从低位到高位】的顺序一一对应的。因为,字符串和数字是两个完全不同的物种,字符串的第 0 个字符是最左边的那个字符,而数字的第 0 位却是最右边的那个数字。就连 dgt 指令,也是 0 表示个位,1 表示十位,2 表示百位,从低到高的顺序。因此,我们将细胞模型的希腊字母串转换成六位数后,读取的顺序也要跟着变为从低位到高位读取。对于 ψααψαψ 这个模型来说,它的第 0 个字符是最左边的 ψ;对于 626226 这个六位数来说,它的第 0 位是最右边的 6。

现在我们从低位开始重新读一下这个六位数:个位的 6 对应 ψ,十位的 2 对应 α,百位的 2 对应 α,千位的 6 对应 ψ,万位的 2 对应 α,十万位的 6 对应 ψ。然后,我们回到第 3 行,从低位开始重新读:个位的 2 对应 α,十位的 4 对应 β,百位的 2 对应 α,千位的 4 对应 β,万位的 2 对应 α,十万位的 4 对应 β。完美对应,毫无冲突。

读完整个 ROM 后,我们会发现:ROM 中的 0 对应空白,2 对应 α,4 对应 β,6 对应 ψ。

再来看芯片代码:

扩大 2 倍后的行号在 3 号芯片被唤醒前,已经被 2 号芯片同步到了自己的 p1 口上。2 号芯片通过 x 口传来的是实时的 X 坐标,收到它后将它放入 acc 寄存(slx x3, mov x3 acc)。这时候我们要检查,当前要打印的细胞模型是否为前 3 行(tcp p1 5)。由于 p1 是扩大 2 倍后的行号,所以当 p1 为 0、2、4 中的一个(即 <5)时,直接将这个数字和一个 0 发送给右边的芯片(- mov p1 x2, - mov 0 x2, - jmp 1)。后面我会详细解释这两个数字的作用。

要打印的不是前 3 行的细胞模型时,我们先将 p1 中的数置为 ROM 地址(mov p1 x1),然后检查电机的 X 坐标是在 0~2 范围内还是 3~5 范围内(tgt acc 2)。如果是在 0~2 范围内,那我们要读取的是低三位中的一位数字,此时我们要空读一格 ROM,让 ROM 指针停在低三位的格子里(- mov x0 null);如果是在 3~5 范围内,那我们要读取的是高三位中的一位数字,ROM 指针初始已经指向了高三位,此时我们需要将 acc 减去 3,让其变成 0~2,令将来的取位指令 dgt 生效(+ sub 3)。做完这些后,我们将取得的高三位/低三位数,以及要取出的位数,都发给右边的 6 号芯片,令它打印出对应的细胞(mov x0 x2, mov acc x2)。

现在回过头来看第 3~6 行。当要打印的细胞模型位于前 3 行时,我们发现要打印的细胞正好是六个 p1,即第 0 行的细胞模型是空空空空空空(000000),第 1 行的细胞模型是 αααααα(222222),第 2 行的细胞模型是 ββββββ(444444)。那么,打印这些行的细胞模型时,我们只需要不停地叫 6 号芯片打印 p1 这个“三位数”(000/002/004)的个位(0/2/4)就行了,不需要关心电机的 X 走到哪了。这也就是满足前面的条件时,我们发给 6 号芯片的两个数字分别是 p1 和 0 的原因(- mov p1 x0, - mov 0 x0)。

接下来是控制电机移动和阀门开关的 4~6 号芯片的代码:

现在该解释为什么 1 号芯片每发一个数字就要睡眠 6 秒了。因为从收到第一个数字起,每隔 6 秒,X 的运动方向改变一次,Y 向上移动一格。所以控制电机 X、Y 的 4、5 号芯片,以及用于记录电机实时 X 坐标的 2 号芯片,都只能 6 秒钟接收一格数据,表示进入了新的一行。在此期间接收会导致线程阻塞。

4 号芯片用来控制电机的水平移动,其 acc 寄存器用于记录电机的水平移动方向,和电机 X 输出端口的电平信号一致,0 表示向左移动,100 表示向右移动。首先将电平信号初始化为 50(mov 50 p1),然后等待 1 号芯片的信号(slx x0)。如果 1 号芯片发送的是非负数(tcp x0 -1),表明需要令电机打印一行新的细胞,此时改变电机的水平移动方向,并将新的方向值发送给发送给电机 X 输出端口(+ not, + mov acc p1)。然后,睡眠 5 秒,表示向左/向右移动 5 格(+ slp 5),此时电机已经从一端移动到了另一端,此时需要令电机停止水平移动(mov 50 p1, slx x0)。而如果 1 号芯片发送的是负数(-1 × 2 = -2),则表明电机需要由 (0, 5) 退回至 (0, 0)。此时因为不需要在 X 方向上移动,所以什么操作都不需要执行,跳回开头继续等待下一次信号就好(mov 50 p1, slx x0)。

5 号芯片用来控制电机的垂直移动。首先将电平信号初始化为 50(mov 50 p1),然后等待 1 号芯片的信号(slx x0)。如果 1 号芯片发送的是非负数(tcp x0 -1),表明需要令电机打印一行新的细胞,此时垂直方向上先等待 5 秒(slp 5),等到水平方向移动到另一个端点后,令电机在 Y 方向上上移一格(+ mov 100 p1, slp 1)。而如果 1 号芯片发送的是负数(-1 × 2 = -2),则表明电机需要由 (0, 5) 退回至 (0, 0)。此时令电机在 Y 方向上下移 6 格,回到原点(- mov 0 p1, slp 5, slp 1)。移动完毕后,令电机停止垂直移动(mov 50 p1, slx x0)。

最后是 6 号用于控制三个阀的芯片。收到 3 号芯片发来的三位数和要提取的位数后(slx x0),我们将三位数放入 acc(mov x0 acc),并将要提取的位数放入 dgt 指令中,提取出对应位的数字(dgt x0)。此时我们获得的一位数就是本秒要打印的细胞,0 对应空,2 对应 α,4 对应 β,6 对应 ψ。首先判断是不是空(tcp acc 0)。如果是空的话,本秒什么都不用打印,关闭一切 + - 号指令,直接跳到最后睡觉。然后是一个典型的“三态判定”,先假设要打印的是 β,激活 DX-300 的第二路信号(+ mov 10 x3),然后开始“三态判定”,检查要打印的是不是另两种细胞(+ tcp acc 4)。如果要打印的是编号为 2 的 α,则撤销之前的设置,改为激活 DX-300 的第一路信号(- mov 100 x3);如果要打印的是编号为 6 的 ψ,同样撤销之前的设置,改为激活 DX-300 的第三路信号(+ mov 1 x3)。信号设置完毕后,休眠一秒,让信号生效(slp 1)。生效一秒后,需要立刻将 DX-300 的信号清除(mov 0 x3)。

点击左下角的【模拟】,稍等片刻,便会弹出结算界面:

评论 (0)

相关阅读
网友评论0条评论

上拉或点击查看更多