虽然知道一定有人写过这样的东西, 好起兴依然驱使我花时间做这样一件事情.
Rubik's Cube 的数据结构如何表现, 在多次失败以后, 发现坐标绝对是超级好用的东西. 在图形编程中, 千万不能小看坐标的威力.
from math import *
class RubikCore(object):
# example of define the data struct of a rubik's cube
R = 0.5 # red
G = 0,1,0 # green
B = 0,0,1 # blue
W = 0,0,0 # white
Y = 1,1,0 # yellow
D = 0,1,1 # dark brown
cube = {}
def __init__(self):
self.init_cube()
self.fill_face()
def init_cube(self):
# create a matrix
seq = (-1, 0, 1)
for x in seq:
for y in seq:
for z in seq:
self.cube[(x,y,z)] = {}
def fill_face(self):
# fill color for every face
seq = (-1, 0, 1)
colors = {(1,0,0): self.R,
(-1,0,0): self.G,
(0,1,0): self.B,
(0,-1,0): self.W,
(0,0,1): self.Y,
(0,0,-1): self.D,}
for x in seq:
for y in seq:
for z in seq:
for i,v in colors.iteritems():
self.cube[(x,y,z)][i] = v
def find(self, axis, value):
# give axis and value find all the objects matched
AXIS = {'x':0, 'y':1, 'z':2}
res = []
for i in self.cube:
if i[AXIS[axis]] == value:
res.append(i)
return res
def _rotate_plane(self, x1, y1):
"""
x'=xcosA-ysinA
y'=ycosA+xsinA
"""
x2 = int(round( x1*cos(-pi/2) - y1*(sin(-pi/2)) ))
y2 = int(round( y1*cos(-pi/2) + x1*(sin(-pi/2)) ))
return x2,y2
def _rotate(self, axis, t):
# pass a tuple(x,y,z)
if axis == 'x':
y,z = self. _rotate_plane(t[1],t[2])
return (t[0],y,z)
elif axis == 'y':
x,z = self. _rotate_plane(t[0], t[2])
return (x, t[1], z)
elif axis == 'z':
x,y = self. _rotate_plane(t[0], t[1])
return (x, y, t[2])
else:
return None
def turn(self, axis, value):
t = self.find(axis, value)
n1 = {}
for i in t:
n1[self._rotate(axis, i)] = self.cube[i]
n2 = {}
#print self.cube[i]
for l in self.cube[i]:
n2[self._rotate(axis, l)] = self.cube[i][l]
#print n2
self.cube[i].update(n2)
self.cube.update(n1)
写了一个数据结构的core, 要显示这个cube, 方法很多, 可以用OpenGL, 用PyGame, 只要继承这个类就可以了.
我自己在调试的时候使用了最偷懒的方法, NodeBox. 而且看起来, 想要找一个不错的3D引擎来搞定这些凡人的活, 还是很有挑战性的. OpenGL的抽象程度还是太低了, NodeBox在3D方面仍然缺乏足够的力量... 这样的工作如果使用Panda3D之类的东西来做, 是不是又有用牛刀的嫌疑?
或许我们真的需要一个能抽象OpenGL的python lib, free your mind的图像玩具, 就像Processing那样.
最后, 这样一个core code的确可以更好的优化一下, 比如把着色的顶点坐标都写进去. 不过剩下的已经基本是体力活了, 作为一个prototype, 要继续它最好是换一种语言(用Flex或者Processing, 至少作为劳动成果可以得到一个swf或者applet放在网上展示)
OK, 总算搞定一件一直都想做的事情.
post on 2008-05-6 17:52