欢迎光临散文网 会员登陆 & 注册

【深圳 IO 攻略】第 5 关:游戏积分器

2022-05-31 21:30 作者:ココアお姉ちゃん  | 我要投稿

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

关卡展示

每当得分信号出现时就 +1 分,犯规信号出现时就 -2 分,但分数不能低于 0 分。(得分和犯规信号不会同时出现)按照上述规则随时更新显示屏上的分数。

根据以上规则,我们很容易设计出如下的算法:

  1. 得分信号出现时,令 acc +1;

  2. 犯规信号出现时,令 acc -2;

  3. 当 acc < 0 时,将 acc 置为 0;

  4. 执行完以上操作后,将 acc 的值发送给显示屏,然后休眠一秒进入下一个时钟周期。

代码如下:

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

优化电量

我们可以看到,这个初版方案的耗电量惨不忍睹。这是因为我们的代码中有很多冗余操作:

  • 得分和犯规信号不会同时为 100,所以 teq p0 100 和 teq p1 100 这两条判断至少有一条是不生效的,效率上有浪费。完全可以改为比较 p0 和 p1 的差值。

  • 仅当触发了犯规信号时,分数才有可能低于 0。没必要每个时钟周期都判断分数是否低于 0。

  • 仅当分数产生变化时才有必要将 acc 的值传给显示器,平时分数没有变化的时候没必要反复传同样的信号。

针对以上几点,我们重新设计一套更优的算法:

  1. 计算犯规信号(p0)和得分信号(p1)的差值;

  2. 当差值为 0 时,当前时钟周期内不做任何操作;

  3. 当差值为 -100 时,说明得分信号激活,令 acc +1,然后将 acc 的值发送到显示器;

  4. 当差值为 +100 时,说明犯规信号激活,令 acc -2。与此同时,立刻判断 acc 是否小于 0。若是,则将 acc 更新为 0。做完以上操作后,将 acc 的值发送到显示器;

  5. 休眠一秒,进入下一个时钟周期,如此循环。

改进后的代码如下:

我在第 3 关的时候说过,测试指令前也是可以带上 + - 号的。这段代码里就出现了这样的条件嵌套。这道题里,每一秒钟可能出现 4 种不同的情况,依次如下:

  • p0 - p1 = 0;

  • p0 - p1 = -100(得分);

  • p0 - p1 = +100, acc - 2 >= 0(犯规,但是没有扣到 0 分以下);

  • p0 - p1 = +100, acc - 2 < 0(犯规且扣到了 0 分以下,强制还原成 0 分)。

我们现在对所有的情况依次讨论:

  • p0 - p1 = 0,此时在执行了 tcp p0 p1 指令后,所有带 + - 前缀的指令都会被关闭,直接跳到最后一行【slp 1】(当前时钟周期内不做任何操作)。此时的代码看起来是这样的:

  • p0 - p1 = -100,此时在执行了 tcp p0 p1 指令后,带 - 前缀的指令会被激活,接下来会执行第 2 行的【- add 1】、第 7 行的【- mov acc x1】和第 8 行的【slp 1】指令(令 acc +1,然后将 acc 的值发送到显示器)。此时的代码看起来是这样的:

  • p0 - p1 = +100 且 acc - 2 >= 0,此时在执行了 tcp p0 p1 指令后,带 + 前缀的指令会被激活。然后会执行第 3 行的【+ sub 2】和第 4 行的【+ tlt acc 0】指令。接下来,由于 acc - 2 >= 0,所以执行完 tlt 测试指令后,带 + 前缀的指令会变为关闭状态,带 - 前缀的指令会变成激活状态。接下来直接执行第 7 行的【- mov acc x1】和第 8 行的【slp 1】指令(令 acc -2,然后将 acc 的值发送到显示器)。此时的代码看起来是这样的:

  • p0 - p1 = +100 且 acc - 2 < 0,直到第 4 行前都和上一条无异。但是此时,因为 acc - 2 < 0,所以 tlt 测试指令执行完后的结果是 + 前缀指令保持激活,- 前缀指令保持关闭。因此接下来执行的是第 5 行的【+ mov 0 acc】、第 6 行的【+ mov acc x1】和第 8 行的【slp 1】(acc -2 后发现小于 0,将 acc 强制置零,然后将 acc 的值发送到显示器)。此时的代码看起来是这样的:

耗电大幅减少到 170,可喜可贺。

附:一些简单的逻辑嵌套

下面我给出一些简单的逻辑嵌套定式,读者可以尝试自行推理证明。

所以以上代码中:

两条测试指令间构成了【与】关系,“仅当 p0 - p1 > 0 且 acc - 2 < 0 时,才将 acc 置 0 并发送给 x1”,“只要以上有一条不满足,那么就执行 - 前缀的部分,只要将 acc 发送给 x1 就可以了,不需要将 acc 置零。其中若 p0 - p1 < 0 时还要额外执行一条 add 1 指令”。

【深圳 IO 攻略】第 5 关:游戏积分器的评论 (共 条)

分享到微博请遵守国家法律