前言

今天在玩游戏,Turing Complete。发现右手法则,无法检测到左手有空位的地方,而是直接检测右手有空位就从下面回去了,想了大概一个小时,想不明白。后来由于百思不得其解,遂上CSDN一查算法,发现了这一篇文章《迷宫算法,右手法则》发现漏了一条,在前面和右边都有障碍的时候,应该向后转,而不是仅仅向右转。于是写下此文,做一下记录。

3ce57a6f675f443aa98f14728308697.jpg

1. 正文

1.1 算法

其实就是简单记录一下算法,所有右手法则的算法为

  1. 直接右转
  2. 查看当前节点的前边是否为墙壁
    1. 是 => 左转,跳转至3
    2. 否 => 直走,跳转至1
  3. 查看当前节点的前边是否为墙壁
    1. 是 => 右转两次(直接向后转),跳转至1(此情况下前边(第二次检查)和右边(第一次检查)都为墙壁)
    2. 否 => 直走,跳转至1

此算法与我在Turing Complete游戏中用的算法一致,并将游戏代码贴至如下(其中游戏中为DSL编辑的汇编语言)

1.2 游戏中的代码

顺便附上一下游戏中的代码,游戏中用的是汇编,虽然是DSL(Domain Specific Language)上的汇编。其中:

  1. 2, 4: 等单行字母的意思为直接向寄存器0输入数字,其意义分别为0: 左转、1: 直走一格、2: 右转、 4: 与前方1格交互查询是什么物品(是否为墙壁)
  2. reg0_to_out: 将寄存器0的值复制到out输出,其余的xxx_to_xxx 皆为此意思
  3. label check, label move_straight: 给当前行定义别名,当直接输入check、move_straight时,相当于无条件输入当前行的值到寄存器0中
  4. jump: 无条件跳转到寄存器0值的地址
  5. equal_0: 当寄存器3的值为0的时候,跳转到寄存器0值的地址
label check
# check right
# (1) if right can go => move
# (2) not move => check current state
2
reg0_to_out
4
reg0_to_out
in_to_reg3
move_straight
equal_0
# after right, turn left back check
# (1) if can go => move
# (2) if not => turn back
0
reg0_to_out
4
reg0_to_out
in_to_reg3
move_straight
equal_0
turn_back
jump

label move_straight
1
reg0_to_out
check
jump

label turn_right
2
reg0_to_out
check
jump

label turn_back
2
reg0_to_out
reg0_to_out
check
jump

总结

复习了一下右手法则,其中非常非常重要的一点,全程摸着一边的墙壁走(这也是现实生活中我们走迷宫的方法!)。然后就是为了保证这一点,当前边和右边都是墙壁的时候,我们要向后转,这样才可以一直摸一边的墙壁,否则则会左右两边的墙壁都摸到!这样就不是右手法则了!

参考

[1] Turing Complete
[2] 《迷宫算法,右手法则》

Q.E.D.


立志做一个有趣的碳水化合物