上文还原了底部两层,接着还原顶面。
按前文所述,假定在绿色为底的情况下,还原了两层,整体翻转为蓝色为底,现要还原顶部绿色面,如下图:
1 算法
算法采用前文引用的参考文献(参考文献的顶部颜色为黄色):
图1 | 图2 |
先还原顶部十字,然后还原整个顶部面,总共用到了三个公式。
1.1 还原顶部十字
还原顶部十字比较简单,只有一个公式,检查魔方顶部符合图中三个条件之一,就可以套用公式,直到出现顶部十字。算法设计如下:
def formula_cmd(command_list):
try:
for command in command_list:
eval(command)()
except:
pass
def 出现顶部绿十字():
color_list=[cube_list[1][3][0],cube_list[2][4][0],cube_list[1][5][0],cube_list[0][4][0]]
if color_list.count('green')==4:
return True
else:
return False
def 顶部一字绿():
color_list = [cube_list[1][3][0], cube_list[1][4][0], cube_list[1][5][0]]
if color_list.count('green')==3 and cube_list[3][4][0]=='green':
return True
else:
return False
def 还原顶部绿十字():
while not 出现顶部绿十字():
if (cube_list[3][4][0]!='green' or cube_list[3][7][0]!='green'):
if not 顶部一字绿():
right()
continue
formula_cmd(["F", "R", "U", "Rp", "Up", "Fp"])
pass
1.2 还原顶部面
这一步较难,公式有两个,对应两个顶部状态,这两个公式的作用是可以分别将三个顶部棱侧面的颜色翻到顶部面,如果符合两个状态,则可以还原顶部。但是,顶部状态不只这两个,对于其他状态,也可以通过反复调用这两个公式,将其他状态转换为图中的两个状态,并最终还原顶部面。
传统的思维方法是采用OOA中的方法,建立状态转换图,然后根据状态转换图,建立“状态-动作‘’判定表,就可以解决此问题,但问题是状态有点多,需要分析出全部状态,和全部状态转换,工作量太大,因而不适合,需要转换思路。状态转换图(局部)如下(此例顶部为蓝色):
思路转换方法:观察图2中的状态,通过实验,发现不管顶部状态怎么变化,都可以按蓝色块的数目来分类:5、6、7三种,顶部状态在这三种蓝色块数之间转换,我们需要的是蓝色块数为6的状态,此状态在两种公式之一的转换下,必能还原整个顶部面。所以算法只需要按照图2中的公式,预先计算状态变换前、后的顶部蓝色块数,尽可能朝6靠近,就可以得到我们想要的状态,并最终还原整个顶部面。算法描述如下:
def 顶部绿块数(): #计算顶部绿色块数
count=0
for i in range(3):
for j in range(3,6):
if cube_list[i][j][0]=='green':
count+=1
return count
def planA绿块数(): #计算如果使用公式1,顶部达到的绿色块数
blue_cell_number=顶部绿块数()
color_list=[[cube_list[3][5][0],cube_list[2][5][0]],
[cube_list[3][2][0],cube_list[2][3][0]],
[cube_list[3][11][0],cube_list[0][3][0]]]
for i in range(3):
if color_list[i][0]=='green':
blue_cell_number+=1
else:
if color_list[i][1]=='green': #原来的顶部面的蓝色块被翻到侧面去了
blue_cell_number-=1
return blue_cell_number
def planB绿块数(): #计算如果使用公式2,顶部达到的绿色块数
blue_cell_number=顶部绿块数()
color_list=[[cube_list[3][3][0],cube_list[2][3][0]],
[cube_list[3][6][0],cube_list[2][5][0]],
[cube_list[3][9][0],cube_list[0][5][0]]
]
for i in range(3):
if color_list[i][0]=='green':
blue_cell_number+=1
else:
if color_list[i][1]=='green':
blue_cell_number-=1
return blue_cell_number
def 还原顶部绿面():
while True:
if 顶部绿块数()!=6:
if planA绿块数()==6:
formula_cmd(["L", "U", "Lp", "U","L","U","U","Lp"])
continue
if planB绿块数()==6:
formula_cmd(["Rp", "Up", "R", "Up", "Rp", "U", "U", "R"])
continue
formula_cmd(["L", "U", "Lp", "U", "L", "U", "U", "Lp"])
else:
if planA绿块数()==9:
formula_cmd(["L", "U", "Lp", "U", "L", "U", "U", "Lp"])
break
if planB绿块数()==9:
formula_cmd(["Rp", "Up", "R", "Up", "Rp", "U", "U", "R"])
break
right()
2 运行结果
现在离最终计算机自动还原魔方只有两个步骤了。