找回密码
 马上注册

QQ登录

只需一步,快速开始

查看: 12154|回复: 5

解魔方机器人[五]-植入算法

  [复制链接]
发表于 2016-9-5 17:54:38 | 显示全部楼层 |阅读模式
本帖最后由 xvholly 于 2016-9-9 12:03 编辑

到此为止,魔方的扫描与计算机表示都已经完成,解决步骤的算法实现,应该说与EV3传感器和马达没有太多的关系,主要是由计算机完成的。魔方的解决是基于群论实现的,说实话我本人并没有对这种理论算法做进一步深入的研究,因为他确实需要时间去学习。好在一些网站早已经将这部分算法实现,并开源出来。Tomas Rokicki的个人主页包含了大量的算法和程序实现,感兴趣的同学强烈推荐:http://tomas.rokicki.com/
5.1 算法程序编译与使用
Tomas Rokicki曾发起过一次解魔方编程活动,所有参赛的程序都是开源的。同样,感兴趣研究魔方算法的同学可以自行围观:http://tomas.rokicki.com/cubecontest/winners.html
如前所述,我只是需要在EV3中使用这些程序,下载其中一个代码,然后按照代码所使用的编程语言进行编译,即可得到可执行的文件。
在此我使用页面中排名第2的程序(pochmann),作者使用C++,因此我们使用C++编译器将代码编译为可执行程序。以g++编译器为例,执行:
  1. g++ JohnnyX.cpp -o pochmann.exe
复制代码
所获得的pochmann.exe即为解魔方算法的可执行文件。参照这个程序的使用说明,程序的使用方法是:
  • 输入:可执行文件 魔方的状态表示
  • 输出:魔方的解法
新的问题出现了,程序输入中的魔方的状态表示是什么样的?跟我们在上一章整理的表达式有什么关系吗?
5.2 魔方色块表示法
先来看个结论,采用色块表示法,一个还原的魔方可表示为:
UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR
不要被这个东西吓到,我们慢慢来看,就会发现并没有那么难。
字母含义
这一串字符中,一共包含了6个字母:U F R B L D,分别代表了一个魔方的上面(Up)、前面(Front)、右面(Right)、后面(Back)、左面(Left)、底面(Down)
魔方的轴
也许你会发现一个问题,就是用这6个字母表示魔方的6个面,如果魔方变换了方位那6个面的方向不是也变了?这就需要说明一下魔方的轴。
如果你手边有一个魔方,那么仔细注意魔方6个面的中心点,然后保持中心点的方向不动,试着去转动6个面,你一定会发现,无论你怎么转动这些面,这6个中心点的位置是不会发生变化的。
比如下面这两幅图:打乱前和打乱后,白色、绿色、红色面的中心点并未变化。也即魔方的轴在拧魔方的过程中,相对位置是不会发生变化的。

还原状态

打乱状态
魔方的色块
魔方由8个角块、12个棱块和6个中心块组成。中心块的位置固定在十字架上。每个角块3面有颜色、每个棱块2面有颜色、每个中心块1面有颜色。
由于中心块的相对位置不变,对于角块和棱块可以用每个面所属的方向进行描述。依然,一个还原的魔方棱块和角块可以表示为:
  • 棱块 UF UR UB UL DF DR DB DL FR FL BR BL
  • 角块 UFR URB UBL ULF DRF DFL DLB DBR
新的问题又来了,一个打乱的魔方怎么表示?
打乱魔方的色块表示
首先我们还是来看那个还原的魔方表示:
UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR
现在已经知道了那么表示棱块和角块,但其实这个表示是包含两个隐含属性的,分别是:色块位置、颜色方向
  • 色块位置 UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR
  • 颜色方向 UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR
色块位置很好理解,正如前文所述,就是每个色块位置的方向型表示。而颜色方向可以理解为,色块某一面的颜色与某个中心色块颜色相同,那么这个色块某一面的颜色所属方向,即为那个中心色块颜色的方向。
比如,在下面这个魔方里面,位置处于FR的色块,色块的F面是红色、R面是蓝色,分别与魔方F面和U面的中心点的颜色一样,所以这个色块的颜色方向为:FU。

色块表示

如果理解了上面这个例子,那么再来看色块位置和颜色方向两行的表示,可以说角块的表示方法只是按照“颜色方向”对魔方进行描述,而描述的顺序是按照“色块位置”执行的。
5.3 程序设计
  1. # 将6x9个面的表示转换为12+8个色块的表示
  2. #                   +--5U-+
  3. #                   |0 1 2|
  4. #                   |3 4 5|
  5. #                   |6 7 8|
  6. # +--0F-+--1R-+--2B-+--3L-+
  7. # |0 1 2|0 1 2|0 1 2|0 1 2|
  8. # |3 4 5|3 4 5|3 4 5|3 4 5|
  9. # |6 7 8|6 7 8|6 7 8|6 7 8|
  10. # +-----+-----+-----+--4D-+
  11. #                   |0 1 2|
  12. #                   |3 4 5|
  13. #                   |6 7 8|
  14. #                   +-----+
  15. # 输入:6x9个面的表示法
  16. # 输出:12+8个块的表示法

  17. def cvt2reid(orignal):
  18.   c = str(orignal)

  19.   # 各个面的中心块代表该面的颜色方向
  20.   c2r = {c[5][4]:'U', c[0][4]:'F', c[1][4]:'R', c[2][4]:'B', c[3][4]:'L', c[4][4]:'D'}

  21.   # 按照指定规律进行色块组合
  22.   reid_mode = c2r[c[5][5]]+c2r[c[0][1]]+' '+c2r[c[5][1]]+c2r[c[1][1]]+' '+\
  23.                    c2r[c[5][3]]+c2r[c[2][1]]+' '+c2r[c[5][7]]+c2r[c[3][1]]+' '+\
  24.                    c2r[c[4][5]]+c2r[c[0][7]]+' '+c2r[c[4][7]]+c2r[c[1][7]]+' '+\
  25.                    c2r[c[4][3]]+c2r[c[2][7]]+' '+c2r[c[4][1]]+c2r[c[3][7]]+' '+\
  26.                    c2r[c[0][5]]+c2r[c[1][3]]+' '+c2r[c[0][3]]+c2r[c[3][5]]+' '+\
  27.                    c2r[c[2][3]]+c2r[c[1][5]]+' '+c2r[c[2][5]]+c2r[c[3][3]]+' '+\
  28.                    c2r[c[5][2]]+c2r[c[0][2]]+c2r[c[1][0]]+' '+c2r[c[5][0]]+c2r[c[1][2]]+c2r[c[2][0]]+' '+\
  29.                    c2r[c[5][6]]+c2r[c[2][2]]+c2r[c[3][0]]+' '+c2r[c[5][8]]+c2r[c[3][2]]+c2r[c[0][0]]+' '+\
  30.                    c2r[c[4][8]]+c2r[c[1][6]]+c2r[c[0][8]]+' '+c2r[c[4][2]]+c2r[c[0][6]]+c2r[c[3][8]]+' '+\
  31.                    c2r[c[4][0]]+c2r[c[3][6]]+c2r[c[2][8]]+' '+c2r[c[4][6]]+c2r[c[2][6]]+c2r[c[1][8]]

  32.   # 返回色块表示列表
  33.   return reid_mode

  34. # 借助编译好的解魔方可执行文件,完成魔方还原步骤
  35. # 此处使用pochmann提供的解决方法
  36. def cube_algorithm(cube_unsolved):
  37.   cube_solved = os.popen('pochmann.exe '+cube_unsolved).readline()
  38.         
  39.   # 返回还原魔方的步骤
  40.   return cube_solved
复制代码

如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
发表于 2016-9-5 18:03:15 | 显示全部楼层
怒赞
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2016-9-6 23:40:19 | 显示全部楼层
可以试试第一名的程序
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2016-9-9 12:00:06 | 显示全部楼层
ntwuhui 发表于 2016-9-6 23:40
可以试试第一名的程序

第一名那个编程风格实在看不懂哈,而且编译也有问题,所以放弃了。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2016-9-10 21:21:07 | 显示全部楼层
xvholly 发表于 2016-9-9 12:00
第一名那个编程风格实在看不懂哈,而且编译也有问题,所以放弃了。

它使用大量宏定义技巧,编译需要的gcc版本比较低,如果将其中>>=改写下,任意gcc都可以,没有问题。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2017-2-11 17:24:25 | 显示全部楼层
学习 学习
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

手机版|中文乐高 ( 桂ICP备13001575号-7 )

GMT+8, 2024-11-21 21:00 , Processed in 0.088330 second(s), 20 queries .

Powered by Discuz! X3.5

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表