【深圳 IO 攻略】第 21 关:精确食品秤

本文首发于 B 站《深圳 IO》文集(https://www.bilibili.com/read/readlist/rl569860)。原创不易,转载请注明出处。
关卡展示

本关要求如下:
显示器初始处于关闭状态。
若在显示器处于关闭状态时按下按钮,则打开显示器。然后,根据【重量】输入的变化,不断更新显示值。题目保证只会在【重量】输入为 0 时开机。
若在显示器显示非 0 重量时按下按钮,则将当前的【重量】输入视为【去皮重量】,显示器显示的实际重量归零。
若在显示器显示 0 时按下按钮,则发送 -999 关闭显示器。题目保证只会在【重量】输入为 0 时关机。例如,【重量】输入和【去皮重量】都为 50 的情况下,实际显示数值也为 0,但游戏不会给出“在这时候按下按钮关机”的测试样例。同时,关机状态下的【重量】输入会一直为 0。
电路图和代码如下:


我们用 dat 来存储【去皮重量】。因为【去皮重量】只可能和某一刻的【重量】输入相等,而【重量】输入又是一个 p 口输入,所以“去皮重量”只可能位于 0~100 之间。因此,我们可以通过【将 dat 置为 0~100 范围外的某个数】来表示【显示器处于关机状态】。这里我们选择了 999,因为当关机时需要发送 -999,去皮重量是 999 时,正好满足 0 - 999 = -999。这样我们发送给显示器的数据就可以统一为“重量输入减去去皮重量的值”,不需要额外的判断了。
首先我们将【去皮重量】初始化为 999,表示显示器初始处于关机状态(@ mov 999 dat)。然后我们检测是否有按钮按下(tcp p0 0)。如果没有按钮按下,则关闭所有 + - 号的指令,跳过更新【去皮重量】的过程,直接跳到第 6 行输出当前的实际重量。当有按钮按下时,我们需要更新【去皮重量】的值。这里我们分三种情况讨论:
当【去皮重量】为 999 时,需要将电源打开。由于开机时的【重量】输入一定为 0,所以此时我们需要将【去皮重量】置为 0。
开机状态下,当【去皮重量】和实际的【重量】输入不相等时,我们为了让显示器归零,需要将【去皮重量】置为当前的【重量】值,确保“重量 - 去皮重量 = 0”。
开机状态下,当【去皮重量】和实际的【重量】输入一致时,我们需要将【去皮重量】置为 999 以关机。
经过分析可以发现,第一条的“将【去皮重量】置为 0”等价于“将【去皮重量】置为当前的【重量】值”。因此我们可以将三种情况合并为两种情况:“当【重量】和【去皮重量】不等时按下按钮,更新【去皮重量】为当前的【重量】值;当【重量】和【去皮重量】相等时按下按钮,更新【去皮重量】为 999。”。我们的第 3~5 行代码描述的正是此逻辑(+ teq p1 dat, - mov p1 dat, + mov 999 dat)。
接下来,无论是否更新了去皮重量,我们都要在这一秒内给显示器发送新的实际重量数值。首先我们将输入的【重量】值放入 acc(mov p1 acc),然后减去【去皮重量】(sub dat)。计算出实际重量后,将该数值发送给显示器(mov acc x3)。做完这些事情后,休眠一秒,进入下一个时钟周期继续监测(slp 1)。
点击左下角的【模拟】,稍等片刻,便会弹出结算界面:
