Haskell中3维字符列表沿三轴旋转的实现问题求助
嘿,作为Haskell和函数式编程的新手,能上手3D魔方解谜项目真的超棒!我来一步步帮你实现三个轴的旋转逻辑——核心思路确实是你说的:针对每个轴,提取对应的2D层旋转后再重组,咱们从基础的2D旋转开始,再扩展到3D的三个轴。
首先,先搞定2D层的旋转,这是所有3D旋转的基础。Haskell里用transpose(转置)和reverse(反转行)就能轻松实现顺时针90度旋转:
-- 顺时针旋转90度一个2D矩阵 rotate2DClockwise :: [[a]] -> [[a]] rotate2DClockwise = reverse . transpose
举个例子,你的myShape里的第一层["CC", " C"],用这个函数旋转后会变成["CC", "C "]——你可以自己手动算一遍:先转置得到["C ", "CC"],再反转行就得到结果了。如果需要逆时针旋转,要么调用三次顺时针,要么用transpose . reverse实现一个rotate2DCounterClockwise。
接下来咱们逐个轴实现3D旋转:
1. 绕Z轴旋转
Z轴是垂直于XY平面的轴,旋转时每个Z层(也就是你myShape里的每个元素)都是独立的XY平面,直接对每个层应用2D旋转就行:
rotateZClockwise :: [[[a]]] -> [[[a]]] rotateZClockwise = map rotate2DClockwise
测试你的myShape:
myShape = [["CC", " C"], [" C", " "]] rotatedZ = rotateZClockwise myShape -- rotatedZ 会是 [["CC", "C "], ["C ", " "]]
2. 绕X轴旋转
X轴是沿着列方向的轴,这时候我们需要提取每个X坐标对应的YZ平面切片,旋转后再重新组合成3D结构。比如X=0的切片是所有层的第0列组成的2D矩阵,旋转后再放回去:
rotateXClockwise :: [[[a]]] -> [[[a]]] rotateXClockwise shape = let xCount = length (head (head shape)) -- X方向的长度(列数) yCount = length (head shape) -- Y方向的长度(行数) zCount = length shape -- Z方向的长度(层数) -- 获取第x个YZ平面切片 getXSlice x = [[shape !! z !! y !! x | y <- [0..yCount-1]] | z <- [0..zCount-1]] -- 旋转每个切片 rotatedSlices = map rotate2DClockwise [getXSlice x | x <- [0..xCount-1]] -- 把旋转后的切片重新组合成3D结构 in [[rotatedSlices !! x !! z !! y | x <- [0..xCount-1]] | z <- [0..zCount-1], y <- [0..yCount-1]]
3. 绕Y轴旋转
Y轴是沿着行方向的轴,类似地,我们提取每个Y坐标对应的XZ平面切片,旋转后重组:
rotateYClockwise :: [[[a]]] -> [[[a]]] rotateYClockwise shape = let yCount = length (head shape) -- Y方向的长度(行数) zCount = length shape -- Z方向的长度(层数) -- 获取第y个XZ平面切片 getYSlice y = [shape !! z !! y | z <- [0..zCount-1]] -- 旋转每个切片 rotatedSlices = map rotate2DClockwise [getYSlice y | y <- [0..yCount-1]] -- 重新组合成3D结构 in [[rotatedSlices !! y !! z | y <- [0..yCount-1]] | z <- [0..zCount-1]]
额外小技巧
- 旋转180度:直接调用两次顺时针旋转就行,比如
rotateZ180 = rotateZClockwise . rotateZClockwise - 逆时针旋转:调用三次顺时针,或者基于2D逆时针函数实现对应的3D函数
你可以把这些函数复制到Haskell环境里,用你的myShape测试每个旋转的效果,慢慢理解每个轴旋转时切片的变化~
内容的提问来源于stack exchange,提问作者xorvralin2
相关产品推荐
相关产品推荐

